機械学習実践 特徴量エンジニアリング

  • 仮説や前処理した結果から得られた知見
  • データサイエンスの知識に基づく知見
  • ドメイン知識に基づく知見

などを用いて、新たな説明変数を構築することです。

説明変数が増えることにより、
機械学習のモデルとしては精度向上に貢献する強力なツールとなりえますが、
その一方で人為的に説明変数を増やすことにより過学習にも陥りやすく、
特徴量エンジニアリングは諸刃の剣とも言える手法です。

支払い状況から特徴量作成

支払い状況を見て、常に支払いが滞っているクライアントは、
今後も支払いが滞る可能性が高いとの仮説があるとます。

この仮説に基づき、PAY_系の指標をすべて合計して、
値が多いクライアントはデフォルトの可能性が高いクライアントである
と仮定してクライアントに対してラベル付けをしましょう!!

data['pay_total'] = (data.PAY_1 + data.PAY_2 + data.PAY_3 + data.PAY_4 + data.PAY_5 + data.PAY_6)
data.head(10)

新たに作成した列を可視化

sns.countplot('pay_total',data=data)
 sns.boxplot(x = data['pay_total'])
data['pay_total'].describe()
count    1000.000000
mean        1.724000
std         3.928264
min         0.000000
25%         0.000000
50%         0.000000
75%         2.000000
max        33.000000
Name: pay_total, dtype: float64

さらに、risk_cat列を作成する。
今回は箱ひげ図を参考に

  • 最小値から中央値までをlow
  • 中央値以降~外れ値を除く最大値までをmedium
  • 外れ値をhigh

としました。

data['risk_cat'] = pd.cut(data.pay_total, [-1,0,5,36], labels=["low","medium","high"])

データ状況から特徴量作成

PAY_X,BILL_AMTX,PAY_AMTXのときの値が全て0であれば、
クレジットカードの支払いには影響しないクライアントにだと考えられます。
このクライアントに対しても新たなclientXの特徴量を作成しましょう!!

payNumList = ['PAY_' + str(i+1) for i in range(6)]
billAmtNumList = ['BILL_AMT' + str(i+1) for i in range(6)]
payAmtNumList = ['PAY_AMT' + str(i+1) for i in range(6)]
clientNumList  = ['client' + str(i+1) for i in range(6)]

clientNumList で、client1~6というコラムを作る

for payNum, billAmtNum, payAmtNum, clientNum 
in zip(payNumList, billAmtNumList, payAmtNumList, clientNumList):
    data[clientNum] = 1 data.clientNumだとダメ
    data.loc[
             (
                 (data[payNum]==0) & (data[billAmtNum]==0) & (data[payAmtNum]==0)), 
             clientNum] = 0 

zipでindexを作る
まず、clientNum を1にする。
そして、data.loc[条件,clientNum] =0にする
そうすることで、条件(payNum,billAmtNum,payAmtNum==0)というのに一致するのが0となる、0 or 1の列を6つ作ることが出来る。

data.columns
Index(['LIMIT_BAL', 'SEX', 'EDUCATION', 'MARRIAGE', 'AGE', 'PAY_1', 'PAY_2',
       'PAY_3', 'PAY_4', 'PAY_5', 'PAY_6', 'BILL_AMT1', 'BILL_AMT2',
       'BILL_AMT3', 'BILL_AMT4', 'BILL_AMT5', 'BILL_AMT6', 'PAY_AMT1',
       'PAY_AMT2', 'PAY_AMT3', 'PAY_AMT4', 'PAY_AMT5', 'PAY_AMT6',
       'default.payment.next.month', 'pay_total', 'risk_cat', 'client1',
       'client2', 'client3', 'client4', 'client5', 'client6'],
      dtype='object')
data
LIMIT_BALSEXEDUCATIONMARRIAGEAGEPAY_1PAY_2PAY_3PAY_4PAY_5PAY_AMT6default.payment.next.monthpay_totalrisk_catclient1client2client3client4client5client6
020000.02212422000014medium111000
1120000.02222602000200014medium111111
290000.02223400000500000low111111
350000.02213700000100000low111111
450000.0121570000067900low111111
995200000.01123900000000low111110
996140000.01114500002149504medium111111
997360000.01113810000011medium100000
99850000.022223000001830010low111111
999120000.01222522000200004medium111111

ドメイン知識から特徴量作成

下記のリンク先の調査によると、
https://zuuonline.com/archives/183430 
若年層(18~34)と中高年層(35over)を比較した場合

  • 若年層は中高年層の2倍の割合で「支払いの遅れ」
  • 若年層は中高年層の3倍の割合で「支払いの遅れの経験」

があることが分かった。

data['AGE'].describe()
count    1000.00000
mean       34.93800
std         9.22818
min        21.00000
25%        28.00000
50%        33.00000
75%        41.00000
max        75.00000
Name: AGE, dtype: float64
data['age_group'] = pd.cut(data.AGE, [21,34,79], labels=['young','middle_senior'])
data.head()
LIMIT_BALSEXEDUCATIONMARRIAGEAGEPAY_1PAY_2PAY_3PAY_4PAY_5default.payment.next.monthpay_totalrisk_catclient1client2client3client4client5client6age_group
020000.0221242200014medium111000young
1120000.0222260200014medium111111young
290000.0222340000000low111111young
350000.0221370000000low111111middle_senior
450000.0121570000000low111111middle_senior
data[data['age_group'] == 'young'].head(10)
LIMIT_BALSEXEDUCATIONMARRIAGEAGEPAY_1PAY_2PAY_3PAY_4PAY_5default.payment.next.monthpay_totalrisk_catclient1client2client3client4client5client6age_group
020000.0221242200014medium111000young
1120000.0222260200014medium111111young
290000.0222340000000low111111young
6500000.0112290000000low111111young
7100000.0222230000000low111111young
8140000.0231280020002medium111111young
10200000.0232340020002medium111111young
1370000.0122301220017high111111young
14250000.0112290000000low111111young
1550000.0233231200003medium111111young

カテゴリカルデータのone-hot-encoding

多くの機械学習モデルではカテゴリカルデータをそのまま値として処理できないので、
.get_dummiesを用いてone-hot-encodingを行います。
【Point】.get_dummiesdrop_first = Trueを指定することで、多重共線性の回避ができます。

data.describe()
LIMIT_BALSEXEDUCATIONMARRIAGEAGEPAY_1PAY_2PAY_3PAY_4PAY_5PAY_AMT5PAY_AMT6default.payment.next.monthpay_totalclient1client2client3client4client5client6
count1000.0000001000.0000001000.0000001000.0000001000.000001000.0000001000.0000001000.0000001000.0000001000.0000001000.0000001000.0000001000.0000001000.0000001000.0000001000.0000001000.0000001000.0000001000.0000001000.000000
mean167080.0000001.5910001.7690001.61400034.938000.3700000.3120000.3210000.2360000.2340005330.3930005102.2910000.2140001.7240000.9820000.9280000.9130000.9020000.8930000.870000
std130632.8386680.4918950.7212210.5303639.228180.8425020.8446120.8687430.7699980.74417616820.51240323669.3635880.4103323.9282640.1330180.2586170.2819760.2974630.3092680.336472
min10000.0000001.0000001.0000001.00000021.000000.0000000.0000000.0000000.0000000.0000000.0000000.0000000.0000000.0000000.0000000.0000000.0000000.0000000.0000000.000000
25%50000.0000001.0000001.0000001.00000028.000000.0000000.0000000.0000000.0000000.000000194.2500000.0000000.0000000.0000001.0000001.0000001.0000001.0000001.0000001.000000
50%140000.0000002.0000002.0000002.00000033.000000.0000000.0000000.0000000.0000000.0000001304.5000001274.0000000.0000000.0000001.0000001.0000001.0000001.0000001.0000001.000000
75%240000.0000002.0000002.0000002.00000041.000000.0000000.0000000.0000000.0000000.0000003739.7500003800.0000000.0000002.0000001.0000001.0000001.0000001.0000001.0000001.000000
max700000.0000002.0000004.0000003.00000075.000008.0000007.0000007.0000007.0000007.000000195599.000000528666.0000001.00000033.0000001.0000001.0000001.0000001.0000001.0000001.000000
payNumList = ['PAY_' + str(i+1) for i in range(6)]
dummyColList = ['SEX', 'EDUCATION', 'MARRIAGE'] + payNumList + ['age_group','risk_cat']
dummyColList →ただのカテゴリ変数のリストを作成
['SEX',
 'EDUCATION',
 'MARRIAGE',
 'PAY_1',
 'PAY_2',
 'PAY_3',
 'PAY_4',
 'PAY_5',
 'PAY_6',
 'age_group',
 'risk_cat']
fnData = pd.get_dummies(data,drop_first=True,columns=dummyColList)
fnData

LIMIT_BAL
AGEBILL_AMT1BILL_AMT2BILL_AMT3BILL_AMT4BILL_AMT5BILL_AMT6PAY_AMT1PAY_AMT2PAY_5_5PAY_5_7PAY_6_2PAY_6_3PAY_6_4PAY_6_6PAY_6_7age_group_middle_seniorrisk_cat_mediumrisk_cat_high
020000.02439133102689.000006890000000010
1120000.026268217252682.0327234553261010000010000010
290000.034292391402713559.0143311494815549151815000000000000
350000.037469904823349291.0283142895929547200020190000000100
450000.0578617567035835.02094019146191312000366810000000100
995200000.039-200-200-200.00608000000000000100
996140000.045397164079941853.0444524543346383160016000010000110
997360000.038000.0000000000000110
99850000.0237800780.039039050007800000000000
999120000.025113348110119111700.0838588643488802050000000000010

1000 rows × 64 columns

columns=dummyColListでダミー変数を作り変数のリストを指定している。

コメント

タイトルとURLをコピーしました