ナード戦隊データマン

データサイエンスを用いて悪と戦うぞ

2017年Kaggleアンケートからデータサイエンティストの給与と関連性が高い回答項目を得る

Kaggle ML and Data Science Survey, 2017 ( https://www.kaggle.com/kaggle/kaggle-survey-2017 )がデータセットとして公開されました。このデータセットに対して、給与を目的変数としてランダムフォレストを回し、各特徴量がどのぐらい給与にとって重要かを得ていきます。(Jupyter notebookで実行する。)

データを読み込む

In[1]:

import pandas as pd
df = pd.read_csv("../input/multipleChoiceResponses.csv",encoding = "ISO-8859-1")
rates = pd.read_csv("../input/conversionRates.csv", encoding="ISO-8859-1")

multipleChoiceResponses.csvは複数回答の項目です。conversionRatesはUSDを1としたときの為替レートです。

前処理

まず、給与を目的変数にするため、給与が未回答の人の項目は除外します。また、国ごとの為替レートをかけて米ドルにあわせます。

In[2]:

import numpy as np

origins = rates["originCountry"].tolist()
exchangeRates = rates["exchangeRate"].tolist()
rate_dict = {}
for origin, exchangeRate in zip(origins,exchangeRates):
    rate_dict[origin] = exchangeRate

df = df[df["CompensationAmount"].notnull()]
df = df[df["CompensationCurrency"].notnull()]
df = df[df["CompensationAmount"].ne("-")]
df = df[df["CompensationCurrency"].isin(rate_dict.keys())]

In[3]:

import re
CompensationUSD = []
currencies = df["CompensationCurrency"].tolist()
amounts = df["CompensationAmount"].tolist()
for currency, amount in zip(currencies,amounts):
    tmp = re.sub(",","",amount)
    CompensationUSD.append(float(tmp)*float(rate_dict[currency]))
df["CompensationUSD"] = CompensationUSD
df = df[df["CompensationUSD"].notnull()]

また、NANを形式的に0で埋めます。さらに、目的変数を給与が50000ドル以上であるかどうかの2値変数として定義します。

In[4]:

df = df.drop('CompensationAmount', 1)
y = df["CompensationUSD"]
X = df.drop("CompensationUSD", 1)
X = X.fillna(0)
X_dummied = pd.get_dummies(X)
y_binary = y > 50000

ランダムフォレストの精度を確認

前処理が完了したので、ランダムフォレストを使います。ランダムフォレストを使う理由は、特徴量の重要性をエントロピーを基に判断できるからです。

In[5]:

from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(X_dummied, y_binary, random_state=0)
clf = RandomForestClassifier(n_estimators=20, random_state=42).fit(X_train, y_train)

print("score:{}".format(clf.score(X_test, y_test)))

Out[5]:

score:0.7367458866544789

70%程度の予測精度があることが確認できます。

特徴量の重要性を出力する

特徴量の重要性を見てみます。

In[6]:

out = pd.DataFrame()
out["feature_name"] = X_dummied.columns.tolist()
out["feature_importance"] = clf.feature_importances_
out.sort_values("feature_importance",ascending=False).to_csv("results.csv", index=False)

上位10件だけみてみましょう。

Out[6]:

Country_United States    0.02148799922371767
Age 0.02079071051576544
Tenure_More than 10 years   0.014385768346026655
CompensationCurrency_INR    0.012900440497789795
CompensationCurrency_USD    0.010117137023914303
Country_India   0.009255688942489685
Tenure_1 to 2 years 0.009019997409959579
CurrentEmployerType_Employed by college or university   0.005851520837770057
LearningCategoryOnlineCourses   0.005459906026947186
Tenure_Less than a year 0.004898482236414723

まず、最も重要なのは、仕事をしている国がアメリカであるかどうかです。 また、年齢も影響が大きいことがわかります。テニュアの年数も強い影響があるようです。 国がインドであるかどうかはアメリカに次いで影響力があります。 さらに、大学から雇用されている場合の影響力も一定程度あるようです。 データサイエンスを学習した方法としてオンラインコースを選択した人も、給与に影響をもたらしていると言えます。

ただ、ロジスティック回帰の係数とは違って、特徴量の重要性は正の影響か負の影響かはわかりません。 そこで、ロジスティック回帰も使ってみましょう。

In[7]:

top_100_features = out.sort_values("feature_importance", ascending=False)[0:100]
X_selected = X_dummied[top_100_features["feature_name"]]
from sklearn.linear_model import LogisticRegression

X_train, X_test, y_train, y_test = train_test_split(X_selected, y_binary, random_state=0)
lr = LogisticRegression().fit(X_train, y_train)

print("score:{}".format(lr.score(X_test, y_test)))

Out[7]:

score:0.8135283363802559

特徴量選択によって精度は上がりました。このモデルの係数を得ます。

In[8]:

out2 = pd.DataFrame()
out2["feature_names"] = X_selected.columns.tolist()
out2["coef"] = lr.coef_[0].tolist()
out2.to_csv("result2.csv", index=False)

上位10件を見てみます。

Out[8]

0    Country_United States   2.348153
1   Age 0.061230
2   Tenure_More than 10 years   0.769692
3   CompensationCurrency_INR    -1.724150
4   CompensationCurrency_USD    -0.017839
5   Country_India   -0.897373
6   Tenure_1 to 2 years -0.568489
7   CurrentEmployerType_Employed by college or uni...   -0.614318
8   LearningCategoryOnlineCourses   -0.003643
9   Tenure_Less than a year -0.601294

プラスとマイナスの符号によって、影響の方向がわかります。アメリカで仕事を得ることがいかに重要であるかがわかるでしょう。

ROCで汎化性能をチェック

最後に、このモデルが汎化性能があることを示すため、ROCをプロットします。

In[9]:

from sklearn.metrics import roc_curve, auc
import matplotlib.pyplot as plt

fpr, tpr, _ = roc_curve(y_test.ravel(), lr.decision_function(X_test))
roc_auc = auc(fpr, tpr)

plt.figure()
lw = 2
plt.plot(fpr, tpr, color='darkorange',
         lw=lw, label='ROC curve (area = %0.2f)' % roc_auc)
plt.plot([0, 1], [0, 1], color='navy', lw=lw, linestyle='--')
plt.xlim([0.0, 1.0])
plt.ylim([0.0, 1.05])
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.title('Receiver operating characteristic example')
plt.legend(loc="lower right")
plt.show()

Out[9]:

f:id:mathgeekjp:20171104170638p:plain

リンク

Which Types of Data Scientists Are Rich? | Kaggle