生き抜くぜ21世紀

統計?機械学習?っぽいことを書く

姓名分割プログラムをつくる-訂正編-

前回の記事に間違いが見つかったのでそんな感じの記事です。

間違いを直す過程でちょっと手法を見直したりしました。

前回までのおさらい

  • 姓名分割プログラムを作ったよ
  • 姓名分割とは、姓名の間にスペースが入っていない人名にスペースを入れることだよ(篠田麻里子→篠田 麻里子)
  • 特徴量はOrderPointとLengthPointだよ
  • LengthPointの計算がなんかバグってるっぽいよ
  • OrderPointとLengthPointの2特徴量でロジスティック回帰をするよ
  • .990の制度が出たよ
  • 詳しくは前回の記事を読んでほしいよ

間違えてたところ

LengthPointの計算がなんかバグってるっぽいよ のところでした

 

やっぱりかよ

ただ単に計算部分のプログラムミスだったんで修正方法は割愛

間違いを直したら

まちがいを直した後にロジスティック回帰をしたところ、どちゃくそ精度が悪くなってしまいました。

回帰の方法については前回に詳しいです。

参考:前回の引用

篠田麻里子を学習用にデータ処理するとこうなります。

Name,OrderPoint,LengthPoint,Answer

篠 田麻里子,0.121212121212121,0.205,0
篠田 麻里子,0.777253191702888,0.616753480620525,1
篠田麻 里子,0.126787212337516,0.246093120543235,0
篠田麻里 子,0.10023598578629,0,0

Answerは正しく区切れているかのbool

 

なんでだろうとおもいながらグラフを書いてみました。

横軸にOrderPoint,縦軸にLengthPoint,赤が正解の区切り位置、青が間違えた区切り位置です。

f:id:rskmoi:20170122220635p:plain

ペロ、、これは多重共線性

多重共線性とは、特徴量(説明変数)同士に相関があるときに回帰がうまくいかなくなってしまう現象です。

OrderPointの係数が5前後なのに対し、LengthPointの係数が10前後になってしまいました。

> plot(OrderPoint,LengthPoint,col = ifelse(Answer == 1, "red", "blue"))
> res = glm(Answer ~ OrderPoint + LengthPoint,data,family = binomial)
> summary(res)
Call:
glm(formula = Answer ~ OrderPoint + LengthPoint, family = binomial,
data = data)
Deviance Residuals:
Min 1Q Median 3Q Max
-3.6175 -0.0433 -0.0301 0.0153 3.9811
Coefficients:
Estimate Std. Error z value Pr(>|z|)
(Intercept) -7.9242 0.1952 -40.60 <2e-16 ***
OrderPoint 5.3504 0.2949 18.14 <2e-16 ***
LengthPoint 12.6333 0.4529 27.89 <2e-16 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
(Dispersion parameter for binomial family taken to be 1)
Null deviance: 28915.4 on 22582 degrees of freedom
Residual deviance: 1747.2 on 22580 degrees of freedom
AIC: 1753.2
Number of Fisher Scoring iterations: 9


これじゃあいけませんので何かしましょう。
こういう時は主成分分析がいいという話になっているので主成分分析をしてみました。

2次元の主成分分析は感覚的にとても理解しやすいのでありがたいですね。

主成分分析(2次元)とは、分散が最大となる軸の回転方法を探す操作のことです。

この姓名分離でいうと、「右にあるのが赤で左にあるのが青!」と一番自信をもって言い切れる回転方法を探す操作のことです。

2次元で評価していたものを1次元で評価することにより、多重共線性により回帰ができなくなる問題を回避するわけです。

f:id:rskmoi:20170123214528p:plain

 こんな感じ

 prcompを使って主成分分析してみると...

> sdata <- cbind(OrderPoint,LengthPoint);
> result <- prcomp(sdata,scale =TRUE)
> summary(result)
Importance of components:
PC1 PC2
Standard deviation 1.392 0.24906
Proportion of Variance 0.969 0.03102
Cumulative Proportion 0.969 1.00000
> print(result)
Standard deviations:
[1] 1.3921087 0.2490648

Rotation:
PC1 PC2
OrderPoint 0.7071068 0.7071068
LengthPoint 0.7071068 -0.7071068

 

PC1で全体の96.9%が説明できて、それは

OrderPoint*0.7071068 + LengthPoint  *0.7071068(ぴったり45°回転!??!?)と言っています。

つまり、OrderPoint+LengthPointが一番大きいやつが正しい姓名分割ができてるやつだ、という計算をすればよいことになります。

なんか本当に合っているのか疑ってしまうくらいぴったりな結果が出てしまいました。

しかしながらこうすることによって式の正しさを保ちながら姓名分離することができるようになりましたとさ。

改めて制度検証

例のサッカー選手データ

前回 4人不正解/394人

今回 5人不正解/394人

 

今度解説するアイマスデータ

前回 3人不正解/174人

今回 4人不正解/174人

 

精度落ちとるやないか!

ということであわてて学習用人名を17000くらい追加したらサッカーデータ5人不正解、アイマスデータが2人不正解まで精度が上がりました。

まとめ

  • 多重共線性っぽかったら、主成分分析をしましょう
  • 計算バグがあって精度が高いよりバグがなくて精度が低いほうが気持ちいい