LoginSignup
4
2

More than 3 years have passed since last update.

【1日1写経】Predict employee attrition【Daily_Coding_001】

Posted at

初めに

  • 本記事は、python・機械学習等々を独学している小生の備忘録的な記事になります。
  • 「自身が気になったコードを写経しながら勉強していく」という、きわめてシンプルなものになります。
  • 建設的なコメントを頂けますと幸いです(気に入ったらLGTM & ストックしてください)。

お題:IBM HR Analytics Employee Attrition & Performance

  • 今回のお題は、IBM HR Analytics Employee Attrition & Performanceです。kaggleに記載のあった説明によると、「従業員の退職理由」を探る問題のようです。
  • 今回、以下のyoutubeの動画を見つつ写経していきました。

Link:Predict Employee Attrition Using Machine Learning & Python

データはkaggleから取ってきました。

Link:IBM HR Analytics Employee Attrition & Performance

分析はyoutubeの動画にある通り、Google Colaboratryを使用しました(便利な時代になったものです)。

Step 1:データ読み込み~内容確認

それではやっていきたいと思います。

1.1: ライブラリのインポート

# ライブラリの読み込み
import numpy as np
import pandas as pd
import seaborn as sns

基本となるライブラリを読み込みます。必要なライブラリはこの後も適宜追加していく感じになります。

次にデータの読み込みですが、kaggleのサイトからダウンロードしたcsvファイルをgoogle colabで読み込みます。

1.2: Google Colabへのファイルのアップロード

# データのアップロード
from google.colab import files
uploaded = files.upload()

これをすることによって、ローカルに保存してあるファイルをgoogle colab上に取り込むことができます。
普段はGoogle Driveにファイルのアップロードしてから、Google Driveを連携させて読み込んでいたので、こっちのほうが楽でいいですね。

1.3: pandasでの読み込み

アップロードしたデータを読み込んでいきます。

# データの読み込み
df = pd.read_csv('WA_Fn-UseC_-HR-Employee-Attrition.csv')

# データの確認
df.head(7)

おなじみのコードですね。次からはデータの中身を確認していきます。

データの中身の確認

以下のコードは(実際には)それぞれ別々に実行していますが、ここでは纏めて書いておきます。

# データフレームの行・列の数確認
df.shape

# それぞれの列の中身のデータ型を確認
df.dtypes

# 欠損値の確認
df.isna().sum()
df.isnull().values.any()

#基礎統計量の確認
df.describe()

# 退職者と在籍者数の数の確認(被説明変数の数の把握)
df['Attrition'].values_counts() #図1

# 退職者と在籍者数の可視化
sns.countplot(df['Attrition'])

# 年齢別の退職者数と在籍者数の可視化
import matplotlib.pyplot as plt
plt.subplots(figsize=(12,4))
sns.countplot(x='Age', hue='Attrition', data=df, palette='colorblind') #図2

【図1】
Attrition1.png

【図2】
Attrotion2.png

ここまではいつもやるようなデータの確認です。まずしっかりデータの中身を確認することはやはり必要だと思います。

1.4: object型のユニーク値の確認

次に、先ほど確認したデータ型のうちobject型の列のユニーク値を確認します。

for column in df.columns:
  if df[column].dtype == object:
    print(str(column) + ':' + str(df[column].unique()))
    print(df[column].value_counts())
    print('___________________________________________')
  1. 1行目:forループでそれぞれの列を繰り返しとってくる
  2. 2行目:取ってきた列がobject型か判定
  3. 3行目:カラム名 + そのカラムのユニーク値を出力
  4. 4行目:各ユニーク値の個数を出力

1.5: 不要行の削除

.drop()で予測するのに意味をなさない列を削除します。

df = df.drop('Over18', axis=1)
df = df.drop('EmployeeNumber', axis=1)
df = df.drop('StandardHours', axis=1)
df = df.drop('EmployeeCount', axis=1)

これは説明不要ですね。退職する理由にならないものをdfの中から外します。

1.6: 列間の相関の確認

これもお馴染みの処理だと思います。各列間の相関(correlation)を確認し、heatmap可視化します。

df.corr()

plt.figure(figsize=(14, 14))
sns.heatmap(df.corr(), annot=True, fmt='.0%')

今回、heatmapを作成する際に指定しているのは以下の2つです。

Item Description
annot True に設定すると、セルに値を出力します。
fmt annot=True に設定した場合、またはデータセットを指定した場合の出力フォーマットを文字列で指定

参考:Seaborn でヒートマップを作成する

1.7: sklearnでカテゴリカル(non numerical)データにラベリング

from sklearn.preprocessing import LabelEncoder

for column in df.columns:
    if df[columen].dtype == np.number:
        continue
    df[column] = LabelEncoder().fit_transform(df[column])

ここでは、sklearnのLabelEncoderを使ってobject型だったデータに数値データに置き換える(「分類器にかける前に文字データを離散値(0, 1, ・・・)に変換」)。

置き換えが終わったら、dfの列の順番を入れ替え分析しやすい形にします。

# Ageを新しい列に複製
df['Age_Years'] = df['Age']

# Age列を落とす
df = df.drop('Age', axis=1)

Step2: sklearnで分析

ここからが本番ですね(前処理が重要なのは言うまでもないですが)。

# dfをデータを説明変数と被説明変数に分割
X = df.iloc[:, 1:df.shape[1]].values
Y = df.iloc[:, 0].values

# 訓練データ、教師データのテストデータサイズ(25%)で分割
from sklearn.model_selection import train_test_split
X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=0.25, ramdom_state = 0)

# ランダムフォレストによる分類
from sklearn.ensemble import RandomForestClassifier
forest = RandomForestClassifier(n_estimators = 10, criterion = 'entropy', random_state = 0)
forest.fit(X_train, Y_train)

上から見ていきましょう。

  • iloc[]を使って説明変数と被説明変数を分離します。
  • sklearnのtrain_test_splitを使って訓練データとテストデータの分割。 train_test_splitの引数は以下の通りです。
Item Description
arrays 分割対象の同じ長さを持った複数のリスト、Numpy の array, matrix, Pandasのデータフレームを指定。
test_size 小数もしくは整数を指定。小数で指定した場合、テストデータの割合を 0.0 〜 1.0 の間で指定します。整数を指定した場合は、テストデータに必ず含めるレコード件数を整数で指定します。指定しなかった場合や None を設定した場合は、train_size のサイズを補うように設定します。train_size を設定していない場合、デフォルト値として 0.25 を用います。
train_size 小数もしくは整数を指定。小数で指定した場合、トレーニングデータの割合を 0.0 〜 1.0 の間で指定します。整数を指定した場合は、トレーニングデータに必ず含めるレコード件数を整数で指定します。指定しなかった場合や None を設定した場合は、データセット全体から test_size を引いた分のサイズとします。
random_state 乱数生成のシードとなる整数または、RandomState インスタンスを設定します。指定しなかった場合は、Numpy のnp.random を用いて乱数をセットします。

(参照: scikit-learn でトレーニングデータとテストデータを作成する)

  • ランファムフォレストを使って分類をします。ここでの引数は、

n_estimators: 木の数の指定(デフォルトは100)
criterion: gini or entropyを指定(デフォルトはgini

この後、forest.fit(...)でモデルを学習させます。

それでは精度を見ていきましょう。

forest.score(X_train, Y_train)

この後、confusion_matrix(混合行列)を使ってAccuracyを計算してます。

from sklearn.metrics import confusion_matrix

cm = confusion_matrix(Y_test, forest.predict(X_test)) #cm: confusion_matrix

TN = cm[0][0]
TP = cm[1][1]
FN = cm[1][0]
FP = cm[0][1]

print(cm)
print('Model Testing Accuracy = {}'.format( (TP + TN) / (TP + TN + FN + FP)))

以上で、簡単ではありますがskleanを使って二値分類の写経になります。

 最後に

内容的にはそこまで難しいものではないにせよ、まだまだ理解していない箇所があることが認識できましたので、引き続き勉強していきたいと思います。

以上。

4
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
2