はじめに
当サイトにも機械学習に関する投稿は数多くありますが、サンプルの実装で利用しているのは、Scikit-learnで言えば付属のIrisの分類など、ある程度整形された学習用のものばかりで、実際に生のデータを利用してデータ分析・予測を行った例は少なく、フラストレーションを感じている方も多いのではないかと考えています。
そこで、自動車保険という期間1年の契約を、翌年、同じ保険会社で更新するか否かがどのような要素と相関するのかを、決定木を用いて分析した例を公開しようと思います。
学習用のサンプルデータと違い、データの加工や出力された結果の解釈など、分析者による独自の工夫が必要となるところがあり、これが正解なのかどうか自信のない部分は多々ありますが、データ分析を行おうとしている方の参考にしてもらえれば幸いです。また、なんらかご指摘あれば是非コメントいただければと思います。
1. 分析の概要
損害保険会社が販売している任意の自動車保険は通常1年の契約であり、1年ごとに更新が必要となります。ここでは、ある年に存在したある保険会社の約1万件の自動車保険の契約を用いて、その契約が翌年に同じ保険会社で更新されたか否かを調べて、どのような契約が同じ保険会社で更新されるか、またどのような契約はされないかを決定木で予測・分析しようとするものです。
但し、車を国内で運転しなくなる等により更新する必要がなくなる場合もありますが、残念ながらその事情は取得できていないためデータに紛れてしまっていることをご了承ください。また、あくまで実データを利用した決定木学習の過程を皆さんの役に立てばと公開するものですので、分析結果に責任を負うものではありません。
2. 分析対象データ
データは最近のある1年間に保険期間が開始したとある県の複数の保険会社の自動車保険の契約データ約1万件であす。その1年間に車の入れ替えなどの異動があった場合はそれを反映したデータとなっています。
これらのデータに、この契約が翌年も同じ保険会社で更新されていなければ0,更新されていれば1の値を持つCLASSデータを付加しています。更新されているか否かは、当年の契約の証券番号と翌年の契約の旧証券番号欄(更新時に入力されることになっている)とのマッチングで判断しています。
3. 特徴量の加工と決定木アルゴリズム
生のデータを機械学習に利用できるようにする工程は単純ではなく、この加工の方法が分析の精度にかなり影響すると考えられます。決定木の場合でも例外ではないでしょう。
ここでは保険契約のデータを利用しますが、そこには保険料や保険金額などの連続変数と性別などのカテゴリー変数が混在しています。またカテゴリーデータも2値(YesかNo)のものもあれば、保険料の割引を決める割引等級のように1から20まで分かれているものもあったりするため、これらをどのように扱うか、または加工するかが重要です。
今回は、これらのカテゴリー変数を、量的変数として扱えるものはそのまま利用し(割引等級は高い方が割引率が高いのでそのまま量的変数としてつかえる)、または量的変数として扱えるように加工して決定木のアルゴリズムとして量的変数を扱えるCARTを採用することとし、Scikit-learnを用いて実装しました。
逆に、量的データをカテゴリー化してCHAIDなどの多分岐をサポートするアルゴリズムで分析する方法も考えられますが、担保別の保険料や保険金額などの量的変数が多いことや、一つのカテゴリーに含まれる値の種類が多岐にわたる項目が多くそれに応じて分岐も多くなり、解釈の難易度が高まる懸念があるため不採用としました。
4. カテゴリーデータの加工
CARTではまずデータを特徴量とその閾値で仮に2つに分離し、分離されたそれぞれのグループのCLASSデータの不純度(エントロピーやジニで)とその両方のグループの不純度を平均したものを計算します。これを総当たり的に閾値と特徴量を変化させていきもっとも平均の不純度の小さいもの(よく分離できているもの)を使って実際に2つに分離します(次の葉=ノードを作るということ)。そして分離してできたノードも同様に分離していきます。
そのときの閾値は、存在する特徴量の中の値の小さいものから順に適用していって一番不純度が少なかったものを採用します。従って、カテゴリー変数であっても順番に意味があるものであれば、それを閾値として利用し、その値より大きいものあるいは少ないものの特徴量のデータのCLASSの数をカウントすればよいわけです。
さきほど述べたように、割引等級はその数値が小さいほうが割引が小さいのでそのまま利用しました。また、普通乗用車、小型乗用車、軽乗用車などの区分を指す用途車種も、小さいほうが排気量が大きいのでそのまま利用しました。(家庭用の自動車保険なので、貨物車等の車種はほぼないので無視しました)
但し、性別などは1が男2が女としてもその順番に意味はないためこの説明は当てはまりませんが、性別のように2値であれば、1と2の間、すなわち1.5より大きいか小さいかで男女の区別の説明がつきます。ただし3値以上だとなんらか他に工夫を行わないとその特徴量を生かせない場合が多いと思います。
例えば、今回の契約には5つの保険会社の契約があり保険会社のコードがデータに含まれています。このコードの大小には意味がありません。そのためここはOne-Hot化しました。つまり、保険会社Aかどうかを0,1で表し、別のフィールドで保険会社Bかどうかを0,1で表すという具合です。但し、これも数多く種類が存在する場合は、その種類で分割した場合に各
種類のデータ量がかなり細分化されると、不純度を計算する決定木の学習方法にはあまり役立たない可能性があります。もしその項目の予測への有用性が高い可能性があると考えるならば、別途その項目に絞って統計的に分析することも検討した方がよいかも知れません。
5. 予測モデル作成と検証
Scikit-learn のDecisionTreeClassifireを使って予測モデル作成のための初期の実装を行ったのが次の図です。不純度の計算に「エントロピー(entropy)」を利用しています。最初のこの例では、max_Depth,Max_leaf_nodesなどの剪定要素は指定していません。
図1の最後のTree構造の絵を見てわかるようにとことん分類され、過学習であろうと想像できます。testデータによる検証の結果、89%程度の精度でした。
次に、MAX_LEAF_NODESを9に指定します。次のようにmodel作成部分のパラメータを追加します。
model = DecisionTreeClasiifire(criterion = 'entropy',Max_leaf_nodes = 9)
図2
精度は95%程度まで向上しました。
この図を見ると、4層目まではある程度分類されるSampleデータの量も多く、また情報利得もそれなりに変化しているのですが、5層目になると情報利得が大きく変化するものはsampleデータの量が極端に小さくなり、過学習になっている疑いがあります。
ここで、パラメータを次のように変更しmax_leaf_nodesを5に変更します。
model = DecisionTreeClasiifire(criterion = 'entropy',max_leaf_nodes = 5)
図3
精度は若干ですが向上し、sampleデータもそれほど小さいものもなくなりました。
max_depth = 3 も試しましたが、こちらのほうがSampleデータの小さいものが省かれていました。
これ以上層または葉を削減しても、精度は上がりませんでしたので、これを予測モデルとしました。
・トレーニングデータの選択による分岐条件の変化
分析データをTrainデータ80% ,testデータを20%に分割していますが、この分割はランダムに行っています。この分割の違いによって(random stateを変更)次の図4のように2層目から分岐条件がが変わるケースがありました。
図4
2層目の右の分岐条件が変化しています。データの件数やClassのばらつきの態様によって、このような変化には注意する必要がありますので、random stateを用いて複数検証することが重要と思います。今回の例では、このモデルでの精度が前のものより低かったので予測モデルとしては前のモデルを採用するようにするべきでしょう。
6. 決定木モデルによるデータマイニング
さて、この予測モデルを利用して、今後締結される契約などについて更新されるかどうかを予測することにも利用できますが、他の機械学習と違いこの決定木は判断に至る過程が見えるという特徴があります。つまりYesかNoかの判断の確実性に疑問があっても、データの要素およびその値と、YesになるあるいはNoになる確からしさとの関連が見えるという大きなメリットがあります。すなわちそれはデータマイニングに利用できるということです。
では、このレベルの木を参考に契約更新しない確率の高いものの契約の条件を考えてみます。
まず、この予測もモデルを使って、データ全体を分類してみましょう。
図5
分類過程を説明する前に、3層目の右端のノードの分岐条件がトレーニング時と異なっていることを記しておきます。パラメーターは変えてませんが全データを使って再度entropyを計算し、分類しなおしています。トレーニングでできた分岐条件をそのまま適用してデータを分類するということではないことに注意が必要です。(もちろんそのように実装することもできますが、その意味はあまりないと考えます)
まず一番上のノードを見ます。これは全体のデータを指し、全部で9708件のデータがあります。そのうちCLASS=0(更新なし)が541件で1(更新有)が9167件です。CLASSのentropy=不純度は0.314です。
最初の分岐条件(閾値)は割引等級が9.5以下かどうかになっています。割引等級は1から20までの1刻みの数値で、数字が大きいほど割引率が大きくなります。(逆に4未満は基準の保険料に対し割増しとなります)
9.5以下の場合(実際は9以下と同義)すぐ左下のノードに行き、9.5より大きい場合は右下のノードに行きます。
entropyは一番上のノードが0.31で、その左下が0.468,右下のノードは0.262です。この左右2つを合わせた平均のentropyを計算すると0.304で、情報利得は0.006です(0.31-0.304)。思ったより小さい数字ですが、特に左下側(yes)の場合は、entropyが0.468となりここだけの情報利得は-0.158で純度が高くなっておりClass=0(更新しない)の割合が全体の割合よりもかなり高まっています。
Value欄を見てわかるようにCLASS=1(更新有)が1795件に対しCLASS=0は199件で、class0の割合が10%近くになりますが右のノードではCLASS=1が7372件に対しCLASS=0が342件で、class0の割合が4.4%にとどまっています。
つまり割引等級が9以下の契約(=割引が33%以下かまたは割増の場合)は更新しない確率が他に比べて高くなるということがわかります。
2層目左側のノードの分岐条件は車両保険金額です。車両保険金額が132.5万円より小さいほう(左下に進むほう)が不純度が大きくなります。割引が33%以下で車両保険金額が132.5万円以下の契約は更新しない比率が12%と他の契約全体に比べ3倍弱高くなります。
割引が小さい保険料の高い契約が更新されないのかと思いきや、車両保険金額が0または低い(=車両損害の保険料が無しか安い)という条件を含めるとさらに更新しない確率が上がるということから保険料だけが更新しない確率が上がる要因ではないと考えられます。契約ごとの合計保険料も特徴量に含まれていますので、保険料によって更新しない確率が大きく変わるのであれば、分岐の条件として現れてもよいはずです。
●注1 車両保険金額は自分の車両の損害も補償する場合に値が入ります。車両の損害の補償を付保していないものは車両保険金額=0としています。また、車両保険金額は車両の新車価格ではなく時価ベースで決まりますので、更新の都度下がっていきます。
●注2 車両保険金額が132.5万円以下で(付保なし含む)、割引等級が9.5以下(通常43%以下の割引または割増)の場合、この条件のものを除く全体の比率の4.5%に対し12%が更新しないことになります。この条件の集合での更新なしとその他の集合での更新なしについては、母比率の差の検定において有意に(5%水準)差があることを確認しています。
●注3 割引等級はノンフリート等級と呼ばれるもので、自動車保険を初めて付保するとき6等級で、1年無事故だと翌年1等級上がります。20また事故があると翌年3等級ダウンします。割引率は事故の有無や年齢条件で同じ等級でも違う場合がありますが。最大は20等級の63%です。4未満は基準の保険料に対し割増しとなります。
2層目右側のノードは用途車種が分岐条件になっています。これが12.5以下のものは普通乗用車(3ナンバー)のみです。その場合、情報利得は0.062となり更新しない割合は3.1%と全体の5.5%より低くなります。
普通乗用車以外(小型乗用車、軽乗用車、原付バイク含む二輪車など)についてはさらに割引等級が分岐条件となっており、18.5より大きいかどうか(実際には19,20のほぼ上限の割引とそれ以外)により分類されます。分類された右の最下段の2つのノードを見ると、更新しない割合に倍近くの開きがあることがわかります。
このように、決定木は予測に利用できるだけでなく、データのマイニングに利用することができます。ここで発見された事項について別途データを調査したり、特徴量を絞り込んで再度決定木分析をすることなどにより深堀も可能になります。
7. 他の事例の紹介
次に他の県のデータを利用して同じく更改の有無の分析を行った事例を取り上げます。
まず、Max_leaf_nodes = 7 のパラメータで全件を対象に分類してみます。結果は以下の通りでした。
図5
最初に分析した県とは違う分類になっています。一層目で用途車種コードを閾値として分類しています。(32より大きいのはほぼ原付バイクで、乗用車は全部左(yes)に分岐します)
右下のノードに進むと不純度が0.391と上のノードの0.236よりかなり大きくなります(不純度が上がる=純度が下がる)。これはCLASS=0(更新なし)の比率が上がったことによります。つまり原付の契約では更新しない確率が平均より高いことを表します。全体の更新しない割合は3.9%程度ですが原付は7%程度です。
次に一番上のノードから左下に進みます。原付を除く乗用車がここに含まれますが、entropyは0.219と情報利得はそれほど多くありません。ここでの分岐条件は保険会社Cかどうかです。この項目の生の形式は業界で割り当てられた保険会社コードです。データ内には6社ありますが、これらのコードをOne-Hot形式に直しており、保険会社ごとに該当の場合1,該当しない場合0を割り当てています。
右下のノードはentropyが0.166と情報利得が大きくなっています。つまりこの保険会社の原付以外の契約については更新する確率が高いことを示しています。
このノードから右下に分岐するのは事故有係数適用期間が0以外のもの(事故を起こして間もないもの)になります。データ量的には少ないですがこの保険会社ついては更新しないものが多くなってます。逆に言うとそれ以外(左下のノード)に進む9割方のデータについては更新しない率が2%とかなり低くなっています。
つまり、この会社の原付以外でかつ事故が最近なかった契約の更新しない確率は、そのデータを除いたものの平均の4.4%の1/2以下となっているということが分かります。
・パラメータの変更による分岐の変化
さて、この分析の面白くないのは、最初に自動車保険としてはマイナーな種類の原付かどうかで分類されてしまっていることです。
試しに、最初の分類が原付に行かないように、Min_samples_leaf を700にしてみましょう。
図6
最初の分岐条件が車両保険金額に変わりました。これは前の県の例では2層目の分岐条件でした。また2層目左のノードは割引率で、これは前に出てきた割引等級にほぼ対応するものです。(上記●注3参照)
実質的には割引等級と同じと考ると、前の例では1層目の分岐条件でした。つまり、原付かどうかを排除すると、前の例と同じような分岐条件が最初の方に現れたということです。
逆に、保険会社Cの分岐はここに現れなくなりました。ちなみに原付のデータをすべて削除したデータで分析すると再度保険会社Cの分岐が現れました。保険会社の分岐の優位性は原付データがあると隠れてしまうということです。
・上の分岐に最後まで引きずられる決定木の宿命
今の例を見てわかるように、決定木は上のノードで分類されたデータをもとにして次の分類を試行して、平均の情報利得が最も大きかったもので実際にデータを分離します。そこでは、分岐に利用する特徴量が何であれ、そのノードに到達しなかったデータは全く利用しないので、その特徴量の持つ本来の情報量への貢献は隠されてしまう可能性があります。この場合だと、一番上で車両保険金額の持つ情報量よりも原付かどうかの情報量の方が分離する効果が高かったので、それ以下の分離は、特徴量が何であれすべて原付かどうかの条件付きの分類になってしまいます。下層に行けば行くほど条件が重なっていき、条件付確率的な分岐になってしまいます。
8. 決定木の活用法
上の分岐に引きずられるのは当然のことですが、このような欠点を改善したものがランダムフォレストと考えられます。特徴量が上位の条件に縛られて、どこかでもっと意味のある分類の要素になるのを妨げられているのを、いろんな条件の決定木を合わせることにより改善したものです。
しかしながらランダムフォレストは予測には適していますがデータマイニングには中が複雑すぎて活用しにくいでしょう。
決定木はパラメーターを変えたり、データの項目を削除・追加を行った場合でも、どのように分類されるのかの過程が見えます。それは、それぞれの特徴量の分類への影響をパラメータを変えたりデータの内容を変えたりと試行錯誤して確認できるということでもあります。これは他の機械学習にはない特徴であり決定木の存在意義であると考えています。
以上