著者の機械学習レベルについて
・機械学習を本格的に勉強し始めてから、ちょうど2.5ヶ月目。SIGNATEにて初めてのコンペに参加しました。初めての本格的に一人でデータ分析することになります。とりあえず、分析期間は7日間として、自分の実力をできる限り出しました。
・分析対象はSIGNATEの「債務不履行リスクの予測」。データサイズは(242156, 10)。データの内容は、借入金額や金利、信用スコアなどが格納されたデータと目的変数である債務不履行か否かのデータが格納されたもの。f1スコアが評価指標。
・本記事の前半がデータ分析、後半がモデリングとなっており、随所考えたことなどが記載されています。
コード:https://github.com/harukicode0/signate_default_prediction_model
データ分析
この前半パートでは本データよりデフォルトしやすい人の特徴を考察する。
ドメイン知識
デフォルトするか否かを予測する前に、金利の決まり方について大雑把に記述する。
金利はその個人・法人がデフォルトするリスクによって決定する。デフォルトするリスクを調査し評価することを格付けと呼び、アメリカのSP社などが企業に対してAAA(←信用スコア)などの格付けをしているのが有名所である。
金利はデフォルトする確率に基づいて設計されているので(ただし、マイカーローンや住宅ローンなどの商品設計されたものは若干違う)、金利を見ればある程度デフォルトする確率がわかる。
また、信用スコアは金利と同様、その個人が所属する集団全体のデフォルト率を評価したものなので、これもまた金利と同様にデフォルトと密接なつながりがある。
信用スコアの決まり方は法人と個人によって違う。法人であれば、決算書や事業内容、業界内でのポジショニング、社風などの定性的情報などによって総合的に決まる。
個人の信用スコアは保証会社等が独自の調査を行なっているため、正確なところはわからないが、個人の年収や年齢、所属会社のポジション、職業、家族構成、持ち家の有無、学歴、借入目的、勤続年数などで決まっているように思える。余談だが、中国のフィンテックである芝麻信用などは個人の購買行動や国籍など従来の金融機関とは違った観点からも信用スコアを算出する。
最後にデフォルト予測で重要になると思われる変数について、2つの観点から考える。
1、金利や個人の属性(年収、会社等)といったその一時のデータ
2、国やその人の所属する業界が不景気になるなどの変化を伴った時系列データのようなもの
両方のデータが揃えば、予測精度が向上しそうだが、今回は1のデータのみのデータしかないので、そこからデフォルトを予測する。
変数の確認
loan_status
今回の目的関数。one-hot-encodingでダミー変数化する。
loan_amnt,purpose
借入金額と借入目的のこと。100~4000の間の数字に収まっている。
借入目的(purpose)別に借入金額を見ると、wedding以外の全ての借入金額が100~4000以内に収まっている。
また、デフォルトの有無別に借入金額のヒストグラムを確認すると、借入金額によってデフォルトの分布の偏りはなさそう。
データの問題点①
movingやcar、house等の借入目的別に借入金額の大きさな差があるはずなのにその差がない(例えば同じ4000という数字でも、movingでは4000は4,000百円,carは4,000の4,000千円,houseの4,000は4,000万円が妥当に思える)。
考えられる原因は全ての借入金額に対して事前にmin-max-scaling(だだし、上限を4,000、下限を100としたもの)を実施しているか、借入金額の単位を合わせずにデータを収集してしまった場合などが考えられる。
term
借入期間のこと。year部分を削除し、量的変数に変換。
期間が長いほどデフォルトする割合が高くなっている。
ただし、この情報では借入期間とデフォルト率の関係が見えてこない。様々な因果ダイアグラムが想像できるが、例えば
①借入金額が大きくなるから借入期間が長くなり、デフォルト率が上昇
②単純に期間が長いから、そこに対する不確実性(不況や首など)が伴いデフォルト率が上昇
などが考えられる。または、期間と金額には交互作用があるのかもしれない。その他、年収などの交絡変数も考えられる(年収が低いと、期間を借入期間を長くする、一方で年収が低いとデフォルトもしやすくなるという経路)。
従って、借入期間別に見た各借入金額のデフォルト率を確認する。
期間3年の借入金額が大きい部分と、期間5年の借入金額が大きい部分を比較すると、期間が長くなるだけでデフォルト率が上がっているように見える。故に、上記2のようなただ、単純に期間が長いからデフォルトするという可能性も捨てきれない。
データの問題点②
借入期間が3年と5年のデータしかない。
仮にhouse_loanであるならば借入期間が30年になってもおかしくないが、このデータ上では借入期間が3、5しか存在しない。
これは仮説だが、今回のローンは無目的ローン(フリーローン)でその使用用途をpurposeに記述しているだけならば、借入金額の上限が決まっていることや後程説明する金利が異様に高いこと、期間が3年5年と短い期間しかないことにも若干納得できる(ただし、無目的ローンは借入目的を言わなくてもいいので、purposeに欠損値がないのが疑問になる)。
interest_rate
現代の日本水準で見ても異様に高い水準。平均13.9%、最大値30.9%の金利となっている。
データの問題点③
このデータがどのような時代背景、場所で取得されたデータなのかがわからない。
今の日本の上限金利を突破しており(法律違反云々はおいといて)、少なくとも直近の日本のデータではなさそう。
データが取られたシチュエーションはわからないが、考えられる可能性としては
・平成3年11月1日から平成12年5月31日の日本(上限金利より推測)(https://www.yamanaka-seiri.jp/cont6/75.html)
・外国
・様々な時代背景、地域を持ったデータをとりあえず結合させたデータ。
などが考えられる。可能性はいくらでも列挙できそうだが、わからないので深掘りしないようにする。
grade
顧客の格付け。
各グレードでデフォルトの有無に違いがあるか確認。
デフォルトの有無により分布にズレがあることはわかる。
次に各gradeで完済者の割合を確認する。
グレードが悪くなるほど、完済者比率が下がっていることがわかる。従って、グレードを順序尺度(順番に意味はあるが、その間隔に意味はない変数)に変換する。変換後はA1は1、G5は35となっている。
データの問題点④
順位尺度に直したgradeとinterest_rateの相関がほぼ1になっている。
これはドメイン知識的には当たり前のことで返済見込みの高い顧客の金利は低く、逆に返済見込みの低い顧客の金利は高くなるように金利は設計されている(金融業界の人から見たら若干語弊のある言い方になっています)。データと知識が整合しており違和感はないが、線形・非線形回帰など、何らかの分析する際には、多重共線性に注意を払わなければならない。
employment_length
このデータセットで唯一欠損値がある特徴量。
勤続年数別に見たデフォルトの有無の人数をヒストグラムにする。
データの問題点⑤
問題は2つある。
①勤務年数10年のポイントに人が集まりすぎている点。
銀行などの金融機関では貸出する際に勤務年数を聞く。したがって、ドメイン知識的にはデフォルトを予測するための重要な変数だと思われる(一方でIT業界などは転職活動が盛んなため、一概に重要な変数ということはできない)。グラフに異常な偏りがある理由は、おそらく10年以上勤務年数がある人も10年のところに含めて集計した結果だと思われる。10年以上の顧客を本来の勤続年数に戻した上で分析をしたい。そのために手法としてemployment_lengthとloan_status以外の変数で勤務年数を回帰などが考えられる。しかし、特徴量を確認すると勤務年数を予測することができそうな変数はない。唯一、grade(勤務年数が長いとgradeが良いかも)が勤務年数と関係がありそうなためgradeとemployment_lengthの関係を確認する。
見づらいが、各勤続年数でgradeの偏りはなさそうに見えるため、勤続年数10年の人たちを回帰で修正することはできそうない。念の為、後のモデル作成時の時のことを考慮し、employment_lengthが10の場合は1、それ以外の場合は0となる新特徴量を作成。
②欠損値をどう扱うか?
①の理由と同様に欠損値を回帰補完することは厳しそう。そのほかの選択肢として、
①欠損値のレコードを削除する
②employment_lengthのカラムごと削除する
③employment_lengthが欠損値か否かの情報を入れた新カラムを作成する。(今回は①〜③全て試す。)
念の為、employment_lengthが欠損値のみを集めた欠損値データセットと欠損値ではないデータセットで分布が変わっているか目視確認する。より厳密さを求めるのなら、各ヒストグラムで母平均の差の検定や分散の差の検定、またはKL距離を用いた確率分布の一致度合いを計算するなどの方法がありえる。
employment_lengthが欠損値のデータセット
employment_lengthが欠損値ではないデータセット
両図の対角線上にある。カーネル密度推定で作られたヒストグラムを確認すると、分布の形に大きな違いはないように見える。従って上記①〜③の全てを試す(今回予測精度向上に寄与したのは③のみでした)。
purpose
借入目的のこと。one-hot-encodingを実施。問題点はloan_amnt部分に上述。
credit_score
信用スコアのこと。信用スコアと格付けなどはつける主体によってずれがあるので、必ずしも信用スコア=格付けになるとは限らない点が注意点。
gradeとの相関係数は-0.45。credit_scoreは高いほど良く、gradeは低いほど良いので感覚に一致する。ヒストグラムを確認すると、信用スコアが660以下のところで綺麗な曲線を描いていたヒストグラムの形がぶつんと切れている。おそらく、スコア660以下の顧客は貸出対象外だったのだろうと思われる。
各credit_scoreにおけるデフォルトした人の比率を確認する。信用スコアが高いほど、デフォルト比率が小さくなるという結果になり、これはドメイン知識と整合性がある。
application_type
おそらく、対面申し込みとネット経由申し込みだと思われる。one-hot-encodingを実施。
申し込み方法別、勤続年数別にデフォルトの有無をヒストグラムで確認する。申し込み方法がJoin _appでかつ勤続年数が0年の人はデフォルト率がわずかに高くなっている。
上記原因を考察するため、Join_app経由の申込かつ、勤続年数が0年の人に絞り、grade別のデフォルトの有無のヒストグラムを確認する。分布は上記のgrade全体で確認した時と似ており、この部分の顧客層が特別gradeが低いといったことは見当たらない。結論は原因不明。
外れ値
gradeとinterest_raitoの外れ値
散布図を確認し、ドメイン知識と照らし合わせ、外れ値を削除する。
gradeとinterest_raitoの2つの散布図より、gradeが悪いのにも関わらず、interest_rateが低いデータが55個(左側に縦に並んでいるデータのこと)。
これらを削除。
loan_amntの外れ値
結論だけ先に伝えると、外れ値として除去するデータはなし。
以下は考察の結果。
loan_amntが100と4000の両端で急に途切れているので、これらの両端に100未満や4000以上の値が含まれている可能性があるためデータを確認。
両端の度数がそれほど大きくない点から余分な数値を含んではいなさそう。なぜなら、人はキリの良い数字で高いものを売るし、お金も借りる傾向にあるから。若干4000の度数が高いことに違和感はない。一応、貸出金額(loan_amnt)別のデフォルト率を確認する。
これを確認するためにローンの借入金額を100単位でビニングする。ビニング後各階級別にデフォルト率を確認。
両端の値が極端な値になっていないことがわかる。従って、外れ値として除去するのは妥当ではない気がする。
補足:外れ値の判定の仕方について
今回は目で見て外れ値を認定したが、機械的に外れ値認定を行う方法がある。それが
・四分位範囲を使ったIQRに基づく外れ値判定
・マハラノビス距離をとIQRを用いた外れ値判定
・3シグマ判定(2シグマでも4シグマでもOK)。
などだ。
今回上記の「gradeとinterest_raito」などはまさにマハラノビス距離を用いた外れ値認定をすべき案件であったが、時間の兼ね合いと、モデルの正答率の向上具合を見て目分量で十分だと思い利用しなかった。
各データの相関関係について
以下の通り。相対的にgradeとinterst_rate、目的変数であるloan_statusとの相関が高い(それぞれ0.24と0.23)。
仮説
・gradeとinterest_ratioがデフォルトの情報をリークしている可能性がある。そのため目的変数の予測のために利用する。また、2変数同士の相関関係がほぼ1であるので、マルチコを避けるため、どちらか一方を除いて分析する。
・借入期間は長ければ長いほど景気変動などの環境要因を受けやすいのでデフォルト率も高くなる。
・信用スコアが高いほど、デフォルトしにくい傾向にある。
検証
説明可能性を担保するため、ロジスティック回帰とランダムフォレストを利用し仮説検証する。
ロジスティック回帰
自由度調整済み決定係数は0.063とモデルの当てはまりが悪い。
効果は概ね仮説通り。
検証後2つの知見を得た。1つは勤続年数が欠損値の顧客はデフォルトする確率が上昇すること。背景はわからないが、借入する際、勤続年数を申告しなくても借りることができるローンなどがあり、そのローンは審査が緩く、デフォルトしやすい人たちが集まる傾向があったのかもしれない。
f1スコアは0.40と説明可能性があるモデルを作った割には高い。
もう1つは借入目的がsmall_businessだとデフォルトしやすいということ。これは分析時には見落としていた。
借入目的別のデフォルト率。
ランダムフォレスト
ロジスティック回帰で利用した特徴量をそのまま利用。
変数重要度↓を確認すると、こちらでもgradeの重要性が示された。
ほぼgradeで分割されている。
f1スコアは0.39
モデル作成
この後半パートでの目標はこのデータを用いて、デフォルト予測の精度の高いモデルを作成すること。
評価指標
利用する評価指標はf1スコア。f1スコアはrecallとprecisonの調和平均で計算される。
・recallとは実際にデフォルトだった人のうち、デフォルトと予測できた人の割合。
・precisionはデフォルトと予測した人のうち実際にデフォルトした人の割合。
なぜ評価指標にf1スコアを用いるかというと、金融業界の文脈から説明する。
・金融機関では、recallが改善すると、デフォルトする人にお金を貸す必要がなくなるので収益が改善する。
・また、銀行などの金融機関は半公的機関という立ち位置にあり、お金を必要としている人にできる限り、お金を貸し経済を円滑に回していく使命がある(そもそも、資本主義は借金(信用)で回ってる)。precisionが改善すると、お金を必要としている(または、貸すべき)人にお金を貸すことができる。
recallもprecsionも金融機関にとっては大事な指標であるため、今回は2つの調和平均であるf1スコアが評価指標となる。
次元削減
PCA(主成分分析)
purposeカラムをone-hot-encodingし、標準化後主成分分析にかける。
解釈が難しいため今回は採用しない。
第2主成分までの累積寄与率が23%とあまり使えない。
第1主成分と第2主成分の散布図を確認。
散布図を目的変数であるloan_stautsで色分けして散布図で表示。
ちなみに、purposeをone-hot-encodingした際にできたdebt_consolidationという変数を使うと綺麗にクラスタリングできる。これが意味するのは第1主成分と第2主成分を使えば、借入目的がdebt_consolidationであることを高い精度で分類できるということである。今回の目的からは外れため使えず。
特徴量のエンジニアリング
- PolynomialFeaturesモジュールを使い、カラムの一部から交差項と2乗の項を作成。(余談だが、3乗4乗と項を作ると、ロジスティックで非線形の複雑な線を引くことができる。)
以下は重複した特徴量エンジニアリングの記述も含む。
- purposeのone-hot-encoding
- application_typeのダミー変数化
- gradeのA1〜G5に1から35の数値を割り当て
- employment_lengthを欠損値か否かで判定したカラムの作成
- 外れ値の削除。gradeとinterest_rateの関係より55個のデータを削除
- loan_amntの値を100で割ったとき、あまりが0になるものを判定するダミー変数の新カラムを作成。
- 勤続年数が10年とそれ以外で場合分けした新カラムを作成
- loan_amntを100単位でpiningした新カラムを作成
LightGBM
今回のモデルとして利用。
決定木ブースティングアルゴリズムの一種。ブースティングとは1つ前の決定木が間違えたものを元に、次の決定木がその間違いを受け継ぎながら学習する手法。LightGBMは計算が軽く、使い勝手が良いのでよく使われるらしい。精度向上のため、ニューラルネットワークを使うことも考えられるが、今回はPCのスペックを考慮し、LightGBMを利用。
optunaを利用し調整したハイパーパラメータ。
・n_estimators:ブースティング実行の回数
・max_depth:決定木の最大の深さ
・num_leaves:最終ノードの数
・min_child_samples:ノードの最小データ数。この値よりもデータ数が少ないノードを作ることができないようにする。
・learning_rate:学習率
・class_weight:'balanced':目的ラベルのデータの偏りに対して強くする
・reg_lambda:L2正則化
・reg_alpha:L1正則化
(L1とL2を入れることでエストラティックネットと呼ばれる正則化になる。)
結果
最大のf1スコアは0.4056%。
精度向上に寄与した操作を覚えている限りで記述する。
・0.007→0.3919
ハイパラにclass_weight='balanced'を入れると改善。今回は目的変数の正解ラベルが極端に偏っていたため、モデルがそのまま学習すると偏った学習をしてしまう。他解決策として、アンダーサンプリングが考えられる。
他f1スコア向上に貢献したなと思った工夫
・optunaでハイパラ探索
・employment_lengthが欠損値か否かの情報を持たせた特徴量の作成
・2乗項の作成、交差項の作成
・interest_rateとgradeの関係から見えた欠損値の除去
・予測に貢献しない特徴量の除去(ロジスティックのL1正則化、またはロジスティック回帰の係数の結果を見ていらない変数を選択)
今後工夫するなら
・ランダムフォレスト、ロジスティック回帰、LightGBM以外のモデルの利用(ニューラルネットワーク等)
・連続値の交差項の検証が知識不足でできなかったので次回はできるようになりたい。