本資料はOBS授業「ビジネスデータ分析」の第7回授業「顧客管理のためのデータ分析」を補足するものです。使用しているサンプルデータファイル“RFM.csv”は照井伸彦・佐藤忠彦『現代マーケティングリサーチ』所載のデータです。但し、分析作業は原著者とは関係なく、西山が行ったことをお断りしておきます。
最初にデータファイル“RFM.csv”が保存されているフォルダーを作業用ディレクトリーにしておきます(「作業用ディレクトリー」の意味が分からない場合は、Rの利用法を先に勉強して下さい。授業を履修している方はMANABAにRへのガイドブックを提供しています。
dir()
## [1] "RFM.csv" "RFMAnalysis-OBS-Appendix.html"
## [3] "RFMAnalysis-OBS-Appendix.ipynb" "RFMAnalysis-OBS-Appendix.rmd"
## [5] "rsconnect"
データファイルはCSVファイルですから以下のように読み込みます。
rfm <- read.csv(file="RFM.csv")
デーファイルを読み込んだ後、まずは要約して大雑把にデータの中身をみておくが鉄則です。
dim(rfm)
## [1] 2000 5
summary(rfm)
## Customer M F R
## Min. : 1.0 Min. : 467 Min. : 1.00 Min. : 1.00
## 1st Qu.: 500.8 1st Qu.:141747 1st Qu.: 6.00 1st Qu.: 20.75
## Median :1000.5 Median :274411 Median :12.00 Median : 41.00
## Mean :1000.5 Mean :276496 Mean :12.81 Mean : 55.22
## 3rd Qu.:1500.2 3rd Qu.:418265 3rd Qu.:18.00 3rd Qu.: 74.00
## Max. :2000.0 Max. :549795 Max. :40.00 Max. :229.00
## DM
## no :1279
## yes: 721
##
##
##
##
数量データR, F, Mについてはヒストグラムもみておく。これを習慣づけましょう。
par(mfrow=c(1,3)) # 横に3つの図を並べる
hist(rfm$F)
hist(rfm$M)
hist(rfm$R)
変数R, F, Mはそれぞれ「直近来店時からの経過日数」、「累積来店回数」、「累積購買金額」であり、CRMのための基本三因子として活用されるようになってきています。まずはシンプルなデータ活用法である10分位分析(デシル分析)、但しこの資料ではレコード数が2000人と比較的少数のため5分位分析を行ってみることにします。
それには、F,M,Rそれぞれを大小順に並べてから、同じ人数ずつ5つのクラスにわけます。2000人を400人ずつ5つのクラスに分けたうえ、クラスには“F1”から“F5”、“M1”から“M5”、“R1”から“R5”のように名前をつけることにします。元の数量データをその大きさに従って区分し、クラスに名前をつけるわけですから行うことは数値から分類カテゴリーへの変換です。そのためこのような作業をカテゴリー化と言います。
カテゴリー化には“cut”コマンドを使います。クラス名を値とする新たな質的変数は分類のための因子(=ファクター)になります。
まずデータ“F”を区分して、小さい順に“F1”, “F2”, “F3”, “F4”, “F5”とクラス名をつけます。
qt <- quantile(rfm$F, probs = c(0,0.2,0.4,0.6,0.8,1))
rankF <- cut(rfm$F, breaks = qt, labels = c("F1", "F2", "F3", "F4", "F5"), include.lowest = TRUE)
新しい質的変数“rankF”を作りましたから、その内容をみておきましょう。
class(rankF) # 変数の型を調べる
## [1] "factor"
length(rankF) # 含まれている値の数を確認。2000人分。
## [1] 2000
rfm$F[1:20] # 元の数量の値
## [1] 6 4 15 30 12 4 6 15 4 13 19 24 17 25 3 3 11 8 14 24
rankF[1:20] # その数量をカテゴリー化した後のクラス名
## [1] F2 F1 F4 F5 F3 F1 F2 F4 F1 F3 F4 F5 F4 F5 F1 F1 F3 F2 F3 F5
## Levels: F1 F2 F3 F4 F5
table(rankF) # 分布。理屈としては400名ずつのクラスになるはず
## rankF
## F1 F2 F3 F4 F5
## 496 334 389 436 345
同じ値は同じクラスに入るため、値が小数ではなく、整数で値が重複する人が多い場合は、正確に400人ずつのクラスにはなりません。とはいえ、分析に困ることはありません。下の、累積購買金額は1円単位で値が入力されているということもあって、400人ずつのクラスができました。
qt <- quantile(rfm$M, probs = c(0,0.2,0.4,0.6,0.8,1))
rankM <- cut(rfm$M, breaks = qt, labels = c("M1", "M2", "M3", "M4", "M5"), include.lowest = TRUE)
length(rankM)
## [1] 2000
table(rankM)
## rankM
## M1 M2 M3 M4 M5
## 400 400 400 400 400
最後の「直近来店時からの経過日数」は多少工夫をします。経過日数は短いほど良いわけですから、最も短いクラスを高評価の“R5”という名前とし、経過日数が増えるにしたがって“R4”, “R3”, “R2”, “R1”のようにクラス名をつけることにしましょう(そうしなければならないわけではありません)。
qt <- quantile(rfm$R, probs = c(0,0.2,0.4,0.6,0.8,1))
rankR <- cut(rfm$R, breaks = qt, labels = c("R5", "R4", "R3", "R2", "R1"), include.lowest = TRUE)
length(rankR)
## [1] 2000
table(rankR)
## rankR
## R5 R4 R3 R2 R1
## 400 419 387 395 399
各数量変数について5分位クラス名をせっかく付けましたから、それを活用して箱ひげ図を描いてみましょう。
まずはグラフ作成の定番パッケージになっている“ggplot2”をロードします(もしここでエラーが出れば、“ggplot2”インストールしてください)。
library(ggplot2)
累積来店回数(F)の箱ひげ図をrankFで層別化して作成すると、以下のようになります。クラスが最下位の“F1”からより上位のクラスへ移るごとに来店回数が増えていることが再確認できます。
ggplot(rfm, aes(x=rankF, y=F)) + geom_boxplot()
累積購買金額(M)、直近来店時からの経過日数(R)も同様です。
ggplot(rfm, aes(x=rankM, y=M)) + geom_boxplot()
経過日数(R)についても箱ひげ図が理屈にかなっているかをチェックしておきましょう。直近来店時からの経過日数(R)については最も経過日数が少ないクラスを高く評価して“R5”としている点に注意してください。
ggplot(rfm, aes(x=rankR, y=R)) + geom_boxplot()
Rコマンダーでは数値変数を区分したときのクラス名は自動的に同じデータセットに追加されましたが、コマンドで操作しているときは、新しく作った変数が自動的にどこかに追加されることはありません。Rコマンダーで「データセット」というのは、実は「データフレーム(data.frame)」と呼ばれるタイプの変数ですが、データフレームに新しくデータを追加するときは以下のようにします。
rfm <- data.frame(rfm, rankF, rankM, rankR) # 同じ長さ(行数)の表やデータを一つにまとめる
class(rfm)
## [1] "data.frame"
head(rfm) # 最初の何行かをみたいときは"head"コマンドを使う
## Customer M F R DM rankF rankM rankR
## 1 1 311349 6 6 yes F2 M3 R5
## 2 2 509794 4 28 yes F1 M5 R4
## 3 3 176331 15 51 yes F4 M2 R2
## 4 4 402413 30 33 yes F5 M4 R3
## 5 5 16689 12 4 no F3 M1 R5
## 6 6 263978 4 126 no F1 M3 R1
累積来店回数の上位クラス“F5”, “F4”だけを取り出しましょう。
goodF <- subset(rfm, subset = (rankF=="F5"|rankF=="F4")) # 行や列を取り出すときはエクセルよりRのほうが遥かに効率的
dim(goodF)
## [1] 781 8
head(goodF,10)
## Customer M F R DM rankF rankM rankR
## 3 3 176331 15 51 yes F4 M2 R2
## 4 4 402413 30 33 yes F5 M4 R3
## 8 8 125001 15 35 no F4 M2 R3
## 11 11 219339 19 50 yes F4 M2 R3
## 12 12 418277 24 4 yes F5 M4 R5
## 13 13 191852 17 58 yes F4 M2 R2
## 14 14 325230 25 20 no F5 M3 R4
## 20 20 468018 24 46 yes F5 M5 R3
## 23 23 312326 26 4 yes F5 M3 R5
## 24 24 522631 34 25 yes F5 M5 R4
これを更に累積購買金額で絞り込みます。
goodFM <- subset(goodF, subset = (rankM=="M5"|rankM=="M4")) # 来店回数(F)で上位層を取り出した後、購買金額(M)の上位層を抽出する
dim(goodFM)
## [1] 457 8
head(goodFM,10)
## Customer M F R DM rankF rankM rankR
## 4 4 402413 30 33 yes F5 M4 R3
## 12 12 418277 24 4 yes F5 M4 R5
## 20 20 468018 24 46 yes F5 M5 R3
## 24 24 522631 34 25 yes F5 M5 R4
## 26 26 440905 20 34 yes F4 M4 R3
## 27 27 515250 34 21 yes F5 M5 R4
## 32 32 498366 23 13 yes F5 M5 R5
## 35 35 495402 26 54 no F5 M5 R2
## 43 43 547412 31 27 yes F5 M5 R4
## 45 45 472860 22 23 no F5 M5 R4
2回の絞り込みで457人を抽出することができました。ここでどんな顧客が選び出されたのか要約をしておきましょう。
summary(goodFM)
## Customer M F R
## Min. : 4.0 Min. :333292 Min. :15.00 Min. : 1.00
## 1st Qu.: 512.0 1st Qu.:397427 1st Qu.:19.00 1st Qu.:14.00
## Median : 951.0 Median :452068 Median :24.00 Median :27.00
## Mean : 998.3 Mean :448627 Mean :24.08 Mean :27.95
## 3rd Qu.:1490.0 3rd Qu.:504388 3rd Qu.:28.00 3rd Qu.:41.00
## Max. :2000.0 Max. :549795 Max. :40.00 Max. :60.00
## DM rankF rankM rankR
## no :118 F1: 0 M1: 0 R5:132
## yes:339 F2: 0 M2: 0 R4:148
## F3: 0 M3: 0 R3:116
## F4:149 M4:211 R2: 61
## F5:308 M5:246 R1: 0
##
当然ながら、rankFについては“F1”, “F2”, “F3”が、またrankMについては“M1”, “M2”, “M3”が含まれていません。この段階で、前回のダイレクトメール(クーポン付き)に反応して来店した客の割合が\(339/(118+339)=0.74\)となり4人の内の3人がメールに反応したことが分かります。
データの全体を使ってダイレクトメール(クーポン付き)への反応予測モデルを作る方が良いというのはその通りです。
model1 <- glm(DM ~ F + M + R, family=binomial(link="logit"), data=rfm)
summary(model1)
##
## Call:
## glm(formula = DM ~ F + M + R, family = binomial(link = "logit"),
## data = rfm)
##
## Deviance Residuals:
## Min 1Q Median 3Q Max
## -2.5349 -0.7560 -0.3634 0.7937 2.7024
##
## Coefficients:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) -2.193e+00 1.857e-01 -11.810 < 2e-16 ***
## F 9.488e-02 8.553e-03 11.093 < 2e-16 ***
## M 3.505e-06 3.900e-07 8.987 < 2e-16 ***
## R -1.580e-02 2.014e-03 -7.845 4.32e-15 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## (Dispersion parameter for binomial family taken to be 1)
##
## Null deviance: 2614.8 on 1999 degrees of freedom
## Residual deviance: 1910.5 on 1996 degrees of freedom
## AIC: 1918.5
##
## Number of Fisher Scoring iterations: 5
exp(model1$coefficients)
## (Intercept) F M R
## 0.111547 1.099526 1.000004 0.984324
ロジスティック回帰分析における「理論値(fitted.values)」は、それぞれの顧客がダイレクトメールに反応する確率です。これを元のデータセット“rfm”に追加しておきましょう。そのついでに、顧客全体の反応確率がどう分布しているかも見ておきましょう。
rfm$prob <- model1$fitted.values
summary(rfm$prob)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 0.003957 0.120302 0.308469 0.360500 0.570401 0.966078
ggplot(rfm, aes(x=prob)) + geom_line(stat="density")
反応確率の平均値は36%です。これはそもそも前回のダイレクトメールに反応した客の割合36%と符合しています。 ただ、反応確率の分布図をみると、10%未満の低い値に山があり、反応すると期待できそうな人は余り多くはないような印象をうけます。あまり得る所は多くはない図であるのが事実ですね(^^;;)
来店回数の階級(rankF)で層別化した分布図です。これをみると、来店回数の階級ごとに反応確率がハッキリと分離されている(=重なっている)ことが分かります。言葉を変えると、ダイレクトメールに反応して来店するかどうかに対して、それまでの累積来店回数の多寡がハッキリした効果をもっている、そんな理屈になります。もし来店回数とクーポンへの反応が無関係であれば、来店回数でクラス分けしても、クラスごとの反応確率の分布に影響はない、つまり分布図は重なっていなければなりません。
ggplot(rfm, aes(x=prob, color=rankF)) + geom_density()
ロジステッィク回帰分析の計算結果をみても、係数の大きさから察しはつくのですが、こうしてグラフに見える化する手法の方をおすすめしなす。
ggplot(rfm, aes(x=prob, color=rankM)) + geom_density()
積購買金額(M)も反応確率に影響することが上の図をみればわかります。それに対して、直近来店時から経過日数は、特に“R3”, “R4”, “R5”の分布図が重なっています。ということは、経過日数はクーポンへの反応にほとんど影響がないということです。ただ、”R1“クラスだけは来店する可能性がほとんどないことがハッキリしていいます。
ggplot(rfm, aes(x=prob, color=rankR)) + geom_density()
経過日数については、クラス“R1”に含まれるかどうかだけが重要だと言えそうです。
直近来店時からの経過日数で最も下位にある“R1”は、具体的にどの程度の日数がたっている客なのか?この点だけを一応確かめておきましょう。
summary(subset(rfm, rankR == "R1"))
## Customer M F R
## Min. : 6.0 Min. : 467 Min. : 1.000 Min. : 93.0
## 1st Qu.: 477.0 1st Qu.: 89613 1st Qu.: 2.000 1st Qu.:107.0
## Median : 961.0 Median :196858 Median : 4.000 Median :124.0
## Mean : 971.3 Mean :221939 Mean : 4.323 Mean :138.3
## 3rd Qu.:1482.5 3rd Qu.:336870 3rd Qu.: 6.000 3rd Qu.:169.0
## Max. :1999.0 Max. :549734 Max. :10.000 Max. :229.0
## DM rankF rankM rankR prob
## no :372 F1:287 M1:118 R5: 0 Min. :0.003957
## yes: 27 F2: 91 M2:101 R4: 0 1st Qu.:0.021265
## F3: 21 M3: 78 R3: 0 Median :0.041787
## F4: 0 M4: 55 R2: 0 Mean :0.054865
## F5: 0 M5: 47 R1:399 3rd Qu.:0.073996
## Max. :0.250402
上のコマンドの意味は、データセット“rfm”からrankRの値が“R1”である行(=客)だけを抜き取り(subsetコマンド)、その後で要約をする(summaryコマンド)ものです。
これを見ると、経過日数が93日以上になっています(最大は229日経過)。前回のダイレクトメールにも反応していない客がほとんど大半を占めていることが分かります。要するに、最後に来てから3か月以上たっている顧客はダイレクトメールにまずは反応しない。そう予測してもよい。前回ダイレクトメールへの反応実績に基づく限り、こんな見込みがたちそうです。
顧客行動の予測モデルを作成する際には、通常、データ全体を推定に使用するトレーニングデータと予測能力の評価に使うテストデータの二つに分割しています。多くの場合、テスト用に使うデータ割合は10%を目安にしても問題はないと思われます。ここでは全データ2000人からランダムに200人をテスト用に留保し、残りの1800人を予測モデル作成に使うことにします。
テスト用のデータセットを抜き取る方法には複数のやり方がありますが、ここでは最も単純な方法、即ち1から2000までの整数を乱順に並べ替えたうえで、最初の200行をテスト用に、残りをトレーニング用のデータとします。それには“sample”コマンドが便利でしょう。例えば、1から10までの整数を並べ替えるには以下のようにします。
sample(1:10,10)
## [1] 2 9 8 6 7 3 5 4 10 1
2000人の顧客をテスト用の200人とトレーニング用の1800人に分けましょう。
idx <- sample(1:2000, 2000) # 1から2000までを乱順に並べる
test.id <- idx[1:200] # 最初の200個を保存
train.id <- idx[201:2000] # 残りの1800個の数字を保存
test <- rfm[test.id, ] # データセット"rfm"からtest.idで保存された行番号をとりだす
train <- rfm[train.id, ] # 残りの1800行をとりだす
データ全体をスプリットした時点で、トレーニングデータとテストデータの要約を見ておきます。
以下に見るとおり、RFMの各種属性、反応確率、ダイレクトメールへの反応割合とも概ね同じになっているので、二つのグループの傾向は同じであると判定できます。
なお、どの顧客をテスト用にするかにはランダム性があります。したがって残りのトレーニング用1800名も必ずしも確定しているわけではなくサンプリングのたびに変わる余地があります。トレーニングデータを用いたロジスティック回帰分析の結果も本資料の数値とは僅かに異なるかもしれない点を念頭においてください。
dim(train)
## [1] 1800 9
summary(train)
## Customer M F R
## Min. : 1.0 Min. : 467 Min. : 1.00 Min. : 1.00
## 1st Qu.: 501.8 1st Qu.:140687 1st Qu.: 6.00 1st Qu.: 21.00
## Median :1000.5 Median :278800 Median :12.00 Median : 40.00
## Mean :1001.7 Mean :276579 Mean :12.92 Mean : 54.66
## 3rd Qu.:1498.2 3rd Qu.:416328 3rd Qu.:18.00 3rd Qu.: 71.00
## Max. :1999.0 Max. :549795 Max. :40.00 Max. :229.00
## DM rankF rankM rankR prob
## no :1147 F1:439 M1:367 R5:357 Min. :0.003957
## yes: 653 F2:300 M2:341 R4:387 1st Qu.:0.124136
## F3:348 M3:368 R3:356 Median :0.312395
## F4:394 M4:369 R2:353 Mean :0.363261
## F5:319 M5:355 R1:347 3rd Qu.:0.575063
## Max. :0.966078
dim(test)
## [1] 200 9
summary(test)
## Customer M F R
## Min. : 10.0 Min. : 1692 Min. : 1.00 Min. : 1.00
## 1st Qu.: 497.0 1st Qu.:148262 1st Qu.: 5.00 1st Qu.: 20.00
## Median :1001.0 Median :248755 Median :10.00 Median : 46.00
## Mean : 989.4 Mean :275754 Mean :11.87 Mean : 60.23
## 3rd Qu.:1539.0 3rd Qu.:425731 3rd Qu.:17.00 3rd Qu.: 96.25
## Max. :2000.0 Max. :549370 Max. :40.00 Max. :226.00
## DM rankF rankM rankR prob
## no :132 F1:57 M1:33 R5:43 Min. :0.006198
## yes: 68 F2:34 M2:59 R4:32 1st Qu.:0.091570
## F3:41 M3:32 R3:31 Median :0.281554
## F4:42 M4:31 R2:42 Mean :0.335654
## F5:26 M5:45 R1:52 3rd Qu.:0.520197
## Max. :0.960561
まずトレーニング用のデータで行動予測モデルを作成し、その予測モデルを計算には含めなかったテストデータに適用して結果を予測することにします。テストデータについても、実際の行動やYesかNoで分かっていますから、予測された行動と実際の行動を比べることによって予測精度を評価することができます。
model2 <- glm(DM ~ F + M + R, family=binomial(link="logit"), data=train)
summary(model2)
##
## Call:
## glm(formula = DM ~ F + M + R, family = binomial(link = "logit"),
## data = train)
##
## Deviance Residuals:
## Min 1Q Median 3Q Max
## -2.3687 -0.7584 -0.3704 0.8018 2.6850
##
## Coefficients:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) -2.216e+00 1.958e-01 -11.313 < 2e-16 ***
## F 9.498e-02 9.008e-03 10.545 < 2e-16 ***
## M 3.509e-06 4.125e-07 8.507 < 2e-16 ***
## R -1.536e-02 2.128e-03 -7.220 5.21e-13 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## (Dispersion parameter for binomial family taken to be 1)
##
## Null deviance: 2358.0 on 1799 degrees of freedom
## Residual deviance: 1727.5 on 1796 degrees of freedom
## AIC: 1735.5
##
## Number of Fisher Scoring iterations: 5
exp(model2$coefficients)
## (Intercept) F M R
## 0.1090909 1.0996419 1.0000035 0.9847563
(当然であるとも言えるのですが)上の結果“model1”と同様の結果が出ています。テストデータも概ね同じ傾向を示していますから、この予測モデルを適用しても問題はないはずです - ただし、テストデータに含まれる個々の顧客は上の予測モデル作成には使ってはいないことに注意してください。
予測モデルがデータにどの程度フィットしているかをまず確認しておきましょう。
そのため、トレーニングデータについて説明変数から予測される行動と実際にとっていた行動とを比べることにします。この予測された行動とは予測モデルから計算される反応確率が0.5を超えると「反応する(Y)」、0.5未満なら「反応しない(N)」という行動予測のことです。
pred <- predict(model2, newdatda=train, type="response")
yn.yosoku <- ifelse(pred > 0.5, "Y", "N")
yn.yosoku <- as.factor(yn.yosoku)
tbl <- table(yn.yosoku, train$DM)
tbl
##
## yn.yosoku no yes
## N 986 261
## Y 161 392
この表を混同行列と呼びます。
ロジスティック回帰分析に限らず識別分析の各種アルゴリズムが有する予測能力を評価するための指標の多くは混同行列に基づいて算出されます。評価指標は多数ありますが、広く利用されているものを以下に示しておきます。
(tbl[1,1]+tbl[2,2])/(sum(tbl)) # 全体として何パーセントを正しく予測できたか ➡ この指標を「精度」といいます
## [1] 0.7655556
tbl[2,2]/sum(tbl[2,]) # 「反応するだろう」と予測した人の何パーセントが実際に反応したか ➡ この指標を「適合率」といいます
## [1] 0.7088608
tbl[2,2]/sum(tbl[,2]) # 実際に反応した人の何パーセントが事前に予測できていたか ➡ この指標を「再現率」といいます
## [1] 0.6003063
予測モデルの予測能力はテストデータに適用してみることによって評価できます。次に、テストデータについて同じ計算をします。
pred <- predict(model2, newdata=test, type="response") # テストデータについて反応確率を求める
yn.yosoku <- ifelse(pred > 0.5, "Y", "N") # 確率が0.5を超える人は"Y"、0.5未満の人は"N"とする
yn.yosoku <- as.factor(yn.yosoku) # "Y", "N"の文字を分類のための因子(ファクター)にしておく
tbl <- table(yn.yosoku, test$DM) # テストデータに含まれる200人の実際の行動を説明変数R,F,Mから正しく予測できたかを表にする
tbl
##
## yn.yosoku no yes
## N 116 32
## Y 16 36
トレーニングデータに対して求めた指標をテストデータについても求めましょう。
(tbl[1,1]+tbl[2,2])/(sum(tbl)) # 全体として何パーセントを正しく予測できたか ➡ この指標を「精度」といいます
## [1] 0.76
tbl[2,2]/sum(tbl[2,]) # 「反応するだろう」と予測した人の何パーセントが実際に反応したか ➡ この指標を「適合率」といいます
## [1] 0.6923077
tbl[2,2]/sum(tbl[,2]) # 実際に反応した人の何パーセントが事前に予測できていたか ➡ この指標を「再現率」といいます
## [1] 0.5294118
Rコマンダーでは常にた一つのデータセット(データフレーム)が計算対象になっています。そのため、アクティブ・データセットを用いて推定した予測モデルを他のデータセットに対して適用するという発想がないのだと思われます。というより、西山が経済分析を続けてきた長い間、トレーニングデータとテストデータを分けて予測能力を評価するという方法論はほぼ無かったと言えます。手元のデータは全て使用することが、特にデータ数が限られた状態においては、より正確な結果を得る、つまり推定誤差をより小さくするための王道でした。この辺にデータ・サイエンス時代の新しい発想が見られるように感じています。
実際の分析現場では、データを精細にフォローしようと過剰にモデルを複雑にする結果、新しく追加されたデータの予測では失敗するというケースがままあります。これをオーバーフィッテイングと呼んでいます。このオーバーフィッテイングという用語も比較的最近になってクローズアップされてきたものです(悪い意味でのデータマイニングという表現はありましたが)。上の例では、トレーニングデータとテストデータで予測精度にそれほど大きな違いがなくオーバーフィッテイングは生じていないことが分かります。
注: 全データを用いた時の結果“model1”の精度についてはホームワークにしておきましょう。授業を履修した方はパワーポイントに記載しています。