1
$\begingroup$

Assume you have the following artificial dataset

import pandas as pd
import numpy as np
df = pd.DataFrame(np.random.randn(100, 4), columns=list('ABCD'))
df['sex']  = [np.random.choice(['male', 'female']) for x in range(len(df))]
df['weight'] = [np.random.choice(['underweight', 
        'normal', 'overweight', 'obese']) for x in range(len(df)) ]

This produce the following artificial dataset

df.head()
Out[50]: 
          A         B         C         D     sex       weight
0  0.955136  0.802256  0.317182 -0.708615  female       normal
1  0.463615 -0.860053 -0.136408 -0.892888    male        obese
2 -0.855532 -0.181905 -1.175605  1.396793  female   overweight
3 -1.236216 -1.329982  0.531241  2.064822    male  underweight
4 -0.970420 -0.481791 -0.995313  0.672131    male        obese

I am trying to know both the sex and the weigh based on the value of the features A,B,C,D. I learned that this a multi-label classification problem and there is a nice python library that should help (e.g. scikit-multilearn ). However I do not know how this is achieved. Can someone show me how I could train a model and test its accuracy on this artificial dataset? Specifically: 1. Assuming that A,B,C,D are the feature and sex and weight are the label, how to create a test and training sets? The following will not work

X=df[list('ABCD')]
y=[['sex','weight']]
X_train, X_test, y_train, y_test = train_test_split(X, y)
  1. How to you train and test the model?
$\endgroup$
  • $\begingroup$ I am not sure how that library works, but check this: depends-on-the-definition.com/…. I have created a NN following this blog instruction for multi-label classification and worked just fine. Let me know if you still have problem or confused. $\endgroup$ – TwinPenguins Oct 28 '18 at 7:15
  • $\begingroup$ @MajidMortazavi thanks. I will take a look at the library $\endgroup$ – Lapatrie Oct 28 '18 at 7:16
1
$\begingroup$

First of all you would need to encode your target columns.We can use sklearn.preprocessing.MultiLabelBinarizer here:

from sklearn.preprocessing import MultiLabelBinarizer
mlb = MultiLabelBinarizer()

X=df[list('ABCD')]
Y=pd.DataFrame(mlb.fit_transform(df[['sex','weight']].values), columns=mlb.classes_, index=df.index)

yields:

In [75]: Y
Out[75]:
    female  male  normal  obese  overweight  underweight
0        1     0       0      1           0            0
1        1     0       0      0           0            1
2        1     0       1      0           0            0
3        1     0       1      0           0            0
4        1     0       0      0           0            1
5        1     0       1      0           0            0
6        0     1       0      0           0            1
7        1     0       1      0           0            0
8        0     1       0      0           0            1
9        0     1       0      0           0            1
..     ...   ...     ...    ...         ...          ...
90       1     0       0      1           0            0
91       0     1       0      0           0            1
92       1     0       0      0           0            1
93       1     0       0      0           1            0
94       1     0       1      0           0            0
95       1     0       0      0           0            1
96       0     1       0      0           0            1
97       0     1       0      0           1            0
98       1     0       0      0           1            0
99       1     0       1      0           0            0

[100 rows x 6 columns]

now we can use one of the classifiers that support multi-label classification (see Support multilabel:)

Example:

from sklearn.neighbors import KNeighborsClassifier

knc = KNeighborsClassifier()

X_train, X_test, Y_train, Y_test = train_test_split(X, Y)

knc.fit(X_train, Y_train)
Y_pred = knc.predict(X_test)
$\endgroup$
1
$\begingroup$

One option is to combine the labels into a single column with a larger number of classes from the combinations of the original columns. Something of the form y = [0, 1, 2, 3, 4, 5, 6, 7, 8], where:

0 = female, underweight
1 = female, normal
2 = female, overweight
...
7 = male, overweight
8 = male, obese

This will give you a single column (pd.Series) for y. You can use train_test_split as you have in the question.

$\endgroup$
  • $\begingroup$ Thanks for your suggestion. I was looking for something more elegant but this is a good starting point $\endgroup$ – Lapatrie Oct 28 '18 at 10:12
  • 1
    $\begingroup$ Indeed! I would only have offered it as a comment for that reason, but I don't have sufficient reputation to do so yet. That said, whenever I've done multi-classification models I've used the above approach – its not pretty but it works and it's fast. $\endgroup$ – Chris Oct 28 '18 at 10:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.