概要

今週の実験の内容は

  • 回帰分析を用いたデータマイニング

である。3週間の流れがデータ分析(第1週)を行って、回帰分析によるモデル構築(第2週)、そして第3週の他の手法を用いたモデル構築へと繋がるため、今週は多変量解析との内容の重複を避けずにおいた。また同科目の履修を前提としていないため、回帰分析の学習も自習内容として含めてある。

  • Rコマンダーを用いた回帰分析の2つの課題(自習、練習に相当)
  • 解析データを用いた1つの課題(本番)

に取り組んで貰う。

実験の流れ

  1. 配付資料とRコマンダーを照らし合わせながら、出力される情報のどれが配付資料のどれに対応するのかを把握する
    • 回帰係数の推定値: Estimate
      • 切片: Intercept
    • 寄与率: R-Squared
    • 自由度調整済み寄与率
    • てこ比
    • 標準化残差
    • 変数増減法
  2. 保険データの回帰分析、に取り組む (保険データの回帰分析)
    1. 回帰係数の推定
    2. 分散分析によるモデルの有意性の検討や回帰係数の有意性の検討
    3. てこ比や標準化残差などの検討
    4. 変数の増減
    5. 以上を繰り返す
  3. 回帰分析の結果に基づいて、訪問する顧客層を絞り込む (訪問ルールの作成)
  4. 必要に応じて、保険データの回帰分析と訪問ルールの作成を繰り返す

データの説明

TIC2000

tic.data.txtからの要約。

  • CoIL 2000 Challengeで用いられた保険会社の顧客に関するデータ。86個の変数は、契約状況(V44-V85)と社会人口統計学的な変数(V1-V43)を含んでいる。この調査は “Can you predict who would be interested in buying a caravan insurance policy and give an explanation why?” という問いに答えるように集められた。
  • このデータはオランダのデータマイニング会社Sentinent Machine Researchから提供され、現実のビジネスの問題に基づいている。学習用データ(ticdata2000.txt)は5000レコードでcaravan insurance policyの契約の有無(V86)を含んでおり、検証用データ(ticeval2000.txt)は4000レコードで契約の有無(V86)は含んでいない。検証用データの正解は、CoIL 2000 Challengeの開催時には公開されていなかったが、現在はテストデータ(tictest2000.txt)として公開されている。
  • V1-V43のうち、コード化が指定されていない変数はすべて、郵便番号の一桁目のエリアを指している。たとえばV30が9ならばその顧客は郵便番号が9で始まるエリアに家を借りていることを、V31が5ならば郵便番号が5のエリアに持ち家があることを意味する。職業、社会層などもすべて、該当するエリアの箇所が郵便番号の一桁目で埋まっている。
変数

dictionary.txtからの抜粋と要約、の日本語版。

変数分類メモ
V1顧客分類2L0でコード化されている、数字の大きさに意味なし
V2住居数大きいほど住む箇所が多い
V3世帯構成員数の平均人数
V4世帯構成員の平均年齢L1でコード化されている、年齢
V5顧客分類1L2でコード化されている、数字の大きさに意味なし
V6-V9宗教L3でコード化されている、V6+V7+V8+V9は9から12の間。それぞれの宗教を信じる割合?
V10-V13結婚場所を表す変数, 例えばV10が0ならば無し?
V14-V15世帯の大きさL3でコード化されている、なぜかV14+V15は10以下。割合?
V16-V18教育水準L3でコード化されている、なぜかV16+V17+V18はほぼ10、それぞれの年数?割合?
V19-V24職業L3でコード化されている、なぜかV19+V20+V21+V22+V23+V24は9から13の間
V25-V29社会層L3でコード化されている、なぜかV25+V26+V27+V28+V29は9から12の間
V30-V31住居L3でコード化されている、なぜかV30+V31は9か10
V32-V34自動車L3でコード化されている、なぜかV32+V33+V34は9から11の間
V35-V36健康保険L3でコード化されている、なぜかV35+V36は9か10
V37-V41収入L3でコード化されている、なぜかV37+V38+V39+V40+V41は9から13の間
V42平均収入L3でコード化されている
V43購買力L3でコード化されている、1から8の間。
V44-V64各種保険支払い額L4でコード化
V65-V85各種保険契約件数件数

メモの確認用のコード。

table((tic.learn$V16+tic.learn$V17+tic.learn$V18))
table((tic.learn$V19+tic.learn$V20+tic.learn$V21+tic.learn$V22+tic.learn$V23+tic.learn$V24))
table((tic.learn$V25+tic.learn$V26+tic.learn$V27+tic.learn$V28+tic.learn$V29))
table(tic.learn$V30+tic.learn$V31)
table(tic.learn$V32+tic.learn$V33+tic.learn$V34)
table(tic.learn$V35+tic.learn$V36)
table(tic.learn$V37+tic.learn$V38+tic.learn$V39+tic.learn$V40+tic.learn$V41)
各変数のコーディング

L0:分類を表す数字なので、大小関係に意味がなく、名義尺度である。そのままでは説明変数にならない。

ValueLabel
1High Income, expensive child
2Very Important Provincials
3High status seniors
4Affluent senior apartments
5Mixed seniors
6Career and childcare
7Dinki's (double income no kids)
8Middle class families
9Modern, complete families
10Stable family
11Family starters
12Affluent young families
13Young all american family
14Junior cosmopolitan
15Senior cosmopolitans
16Students in apartments
17Fresh masters in the city
18Single youth
19Suburban youth
20Etnically diverse
21Young urban have-nots
22Mixed apartment dwellers
23Young and rising
24Young, low educated
25Young seniors in the city
26Own home elderly
27Seniors in apartments
28Residential elderly
29Porchless seniors: no front yard
30Religious elderly singles
31Low income catholics
32Mixed seniors
33Lower class large families
34Large family, employed child
35Village families
36Couples with teens 'Married with children'
37Mixed small town dwellers
38Traditional families
39Large religous families
40Large family farms
41Mixed rurals

L1:大きさが年齢の順なので、そのまま説明変数に使える。

120-30 years
230-40 years
340-50 years
450-60 years
560-70 years
670-80 years

L2:数字は分類を表すだけなので、連続尺度でも順序尺度でもなく、名義尺度。そのままでは説明変数にならない。

1Successful hedonists
2Driven Growers
3Average Family
4Career Loners
5Living well
6Cruising Seniors
7Retired and Religeous
8Family with grown ups
9Conservative families
10Farmers

L3:順序尺度。このまま連続尺度の説明変数として用いる。

00%
11 - 10%
211 - 23%
324 - 36%
437 - 49%
550 - 62%
663 - 75%
776 - 88%
889 - 99%
9100%

L4: 順序尺度。今回はこのまま連続尺度の変数として用いる。

0f 0
1f 1 - 49
2f 50 - 99
3f 100 - 199
4f 200 - 499
5f 500 - 999
6f 1000 - 4999
7f 5000 - 9999
8f 10.000 - 19.999
9f 20.000 - ?
参考

kernlabパッケージに、加工済みのデータが入っていて、それを使うこともできる。

install.packages(c("kernlab"), dependencies=TRUE)
tic.learn <- ticdata[1:5822,]
tic.eval <- ticdata[5823:9822,]

今回の課題

概要
  • TICデータは、V65からV85までが21種類の保険商品の契約件数である。実験ペアのどちらかの学籍番号の末尾1桁を用いて、分析対象とする保険商品を決めよ。
学籍番号の末尾1桁解析する保険商品
0V75
1V76
2V77
3V78
4V79
5V80
6V81
7V82
8V83
9V84
  • 重回帰分析を行い、分析結果を考察せよ。
  • 重回帰分析の結果を用いて、指定された保険商品の契約に関する予測式を構築せよ。
  • 線形モデルと重回帰分析を用いて、このデータをデータマイニングすることについて、考察せよ。

実験準備

この課題ではMASSライブラリのみ、使う可能性がある。

library(MASS)

1つ目のデータは、Rに次の命令を実行させておく。

x <- c(2.2,4.1,5.5,1.9,3.4,2.6,4.2,3.7,4.9,3.2)
y <- c(71,81,86,72,77,73,80,81,85,74)
data.1 <- data.frame(x=x,y=y)
rm(x,y)

2つ目のデータは、Rに次の命令を実行させておく。

x1 <- c(51,38,57,51,53,77,63,69,72,73)
x2 <- c(16,4,16,11,4,22,5,5,2,1)
y <- c(3.0,3.2,3.3,3.9,4.4,4.5,4.5,5.4,5.4,6.0)
data.2 <- data.frame(x1=x1,x2=x2,y=y)
rm(x1,x2,y)

演習で用いる保険データは、Rに次の命令を実行させておく。

Sys.setenv("http_proxy"="http://130.153.8.66:8080/")
tic.learn <- read.table("http://kdd.ics.uci.edu/databases/tic/ticdata2000.txt")
tic.eval <- read.table("http://kdd.ics.uci.edu/databases/tic/ticeval2000.txt")
tic.test <- read.table("http://kdd.ics.uci.edu/databases/tic/tictgts2000.txt")
tic.eval <- cbind(tic.eval, tic.test)
colnames(tic.eval)[86] <- "V86"
rm(tic.test)

あとはRコマンダーで、data.1、data.2、tic.learnそれぞれについて、回帰分析を進める。

library(Rcmdr)

Rコマンダーで回帰分析をする際に用いるメニュー

Rコマンダーでの回帰分析の手順は、次の通り。

[統計量] -> [モデルへの適合]
[モデル] -> [モデルを要約]
[モデル] -> [逐次モデル選択]
[モデル] -> [部分モデル選択]
[モデル] -> [仮説検定] -> [分散分析]
[モデル] -> [グラフ] -> [基本的診断プロット]
[モデル] -> [グラフ] -> [影響プロット]

この手順で分析を進めながら、参考資料の解析ストーリーと対比させよ。 「モデル選択」は、添付の資料に従うなら、変数増減法だが、その他のことも考えてよいし、 必ずしも選択されたモデルが最適であることもないので、少し変えても構わない。

レポート

レポート提出要領:下記「XXXXXXX」は各自の学籍番号(半角文字)で置き換えること

項目指定
提出期限実験実施の翌週の火曜日の午前10時30分まで
提出方法電子メールに添付 (宛先は配付資料に記載)
ファイル形式Wordファイル (LaTeXで作成する場合は、dvipdfmxでPDFに変換すること)
メールの件名統計工学実験2レポート提出(XXXXXXX)
レポートファイルの名称統計工学実験2_XXXXXXX.doc あるいは 統計工学実験2_XXXXXXX.docx
提出部数レポートは各自1通ずつ。レポートの表紙に、共同実験者の学籍番号と氏名を記すこと。

参考文献

サポート欄

  • data.2のyがひとつ足りなかったのを、追加しました。(1122a)
  • tic.learnというデータ名をtic.leaanとミスタイプしていたのを修正しました。(1122a)
  • インターネットに繋がらないパソコンを使っている人は、TAさんから次の2つのファイルを貰ってください。(1122a)
    • このWikiページのPDFファイル
    • ticdata2000.txt
  • 回帰分析の結果から標準化残差とテコ比の散布図を描くとき、配布資料では残差を標準化するのに、「残差の平方和を残差の自由度で割ったもの」を誤差分散の推定値としますが、Rでは「残差の標本分散」を誤差分散の推定値としています。第5章の例題では、それぞれ「残差平方和/7」と「残差平方和/9」ですので、Rが描く標準化残差のグラフはすべて、配布資料よりも9/7だけ原点から拡大されることになります。(0211p)
  • V1は使わないのがおすすめ。番号の順序に意味がなく、各コードごとの頻度を集計させると、次のようになるため。(0237p)
    > table(tic.learn$V1)
      1   2   3   4   5   6   7   8   9  10  11  12  13  15  16  17  18  19  20 
    124  82 249  52  45 119  44 339 278 165 153 111 179   5  16   9  19   3  25 
     21  22  23  24  25  26  27  28  29  30  31  32  33  34  35  36  37  38  39 
     15  98 251 180  82  48  50  25  86 118 205 141 810 182 214 225 132 339 328 
     40  41 
     71 205 
  • 保険商品ごとに難易度が異なります。V86が一番簡単。
V0123456
V75542638214
V7655291731001181
V77579131
V78578438
V795799194
V80266630171267321
V8158193
V825789312
V835675111342
V845777441

参考

少し加工する

以下の6行は、実行しない方がいい場合もある。

tic.learn$V1 <- as.factor(tic.learn$V1)
tic.learn$V5 <- as.factor(tic.learn$V5)
tic.learn$V86 <- as.factor(tic.learn$V86)
tic.eval$V1 <- as.factor(tic.eval$V1)
tic.eval$V5 <- as.factor(tic.eval$V5)
tic.eval$V86 <- as.factor(tic.eval$V86)

あとはそのまま。

考えたルールに基づく対象限定

各変数に閾値を設けてルールを生成したとする。 たとえば、「V47が5.5以上かつV44が1未満」または「V47が5.5以上かつV1が{1,3,6,8,12,20}のどれか」、というルールは 次のように記す。

(tic.learn$V47>5.5 & tic.learn$V44<1) | (tic.learn$V47>5.5 & (tic.learn$V1==1 |tic.learn$V1==3 | tic.learn$V1==6 | tic.learn$V1==8 | tic.learn$V1==12 | tic.learn$V1==20) ) 

「&」が「かつ(AND)」、「|」が「または(OR)」である。

このルールを検証用データに適用するには、

tic.learn.visit <- (tic.learn$V47>5.5 & tic.learn$V44<1) | (tic.learn$V47>5.5 & (tic.learn$V1==1 |tic.learn$V1==3 | tic.learn$V1==6 | tic.learn$V1==8 | tic.learn$V1==12 | tic.learn$V1==20) ) 

と、訪問するか否かを二値(TRUE, FALSE)で表すオブジェクトを生成する。 このモデルに予測に基づいた訪問の成果を検証するには、訪問対象のリストtic.visitと検証用データの正解V86のクロス集計を行えばよい。

table(tic.learn.visit)

FALSE  TRUE 
 3029   971 

table(tic.learn.visit, tic.learn$V86)

tic.learn.visit    0    1
         FALSE 2878  151
         TRUE   884   87

ここでは、訪問対象に884+87=971人を選定し、そのうちの87人が実際に契約してくれる人だったことになる。 契約率は87/971=8.96%。また誤判別率は

(884+151)/4000

で25.9%となる。

モデルに基づく対象限定

学習したモデルに基づいて、訪問対象を狭めるには、predict()という関数を用いて、訪問対象か否かというリストを作成する。 まず、設定まで調整したモデルを、学習用データ(tic.learn)から得る。

tic.rpart <- rpart(V86~., data=tic.learn, control=c(cp=0.005))

次に、このモデル(ここではtic.rpart)を検証用データ(tic.eval)に適用して、契約してくれるか否かの予測を行う。 この際、0.05という閾値も調整の必要がある。

tic.eval.visit <- predict(tic.rpart, newdata=tic.eval)[,2]>0.05

このモデルに予測に基づいた訪問の成果を検証するには、訪問対象のリストtic.visitと検証用データの正解V86のクロス集計を行えばよい。 V86の保険商品が分析対象の場合は、

table(tic.eval.visit)

tic.eval.visit 
FALSE  TRUE
 2389  1611

table(tic.eval.visit, tic.eval$V86)

tic.eval.visit    0    1
         FALSE 2310   79
         TRUE  1452  159

ここでは、訪問対象に1452+159=1611人を選定し、そのうちの159人が実際に契約してくれる人だったことになる。契約率は159/1452=11.0%。 また誤判別率は

(79+1452)/4000

で38.275%となる。

想定される困難

次の1行を実行すると、かなり時間がかかってエラーになる。

tic.glm.step <- step(glm(V86~., family="binomial", data=tic.learn)

次の4行、いずれもエラーになる。変数間の関係が悪すぎるよう。変数の意味を考えて、追加しないといけないかも。

tic.glm <- glm(V86~V1+V2+V3+V4+V5+V6+V7+V8+   V10+
V11+V12+    V14+    V16+V17+    V19+V20+
V21+V22+V23+    V25+V26+V27+V28+    V30+
        V33+V34+V35+    V37+V38+V39+V40+
    V42+V43+V44+V45+V46+V47+V48+V49+V50+
V51+V52+V53+V54+V55+V56+V57+V58+V59+V60+
V61+V62+V63+V64+V65+V66+V67+V68+V69+V70+
V71+V72+V73+V74+V75+V76+V77+V78+V79+V80+
V81+V82+V83+V84+V85, family="binomial", data=tic.learn)
table(predict(tic.glm, newdata=tic.eval)>0.5)
tic.glm <- glm(V86~     V2+V3+V4+    V6+V7+V8+   V10+
V11+V12+    V14+    V16+V17+    V19+V20+
V21+V22+V23+    V25+V26+V27+V28+    V30+
        V33+V34+V35+    V37+V38+V39+V40+
    V42+V43+V44+V45+V46+V47+V48+V49+V50+
V51+V52+V53+V54+V55+V56+V57+V58+V59+V60+
V61+V62+V63+V64+V65+V66+V67+V68+V69+V70+
V71+V72+V73+V74+V75+V76+V77+V78+V79+V80+
V81+V82+V83+V84+V85, family="binomial", data=tic.learn)
tic.glm <- glm(V86~V44+V45+V46+V47+V48+V49+V50+
V51+V52+V53+V54+V55+V56+V57+V58+V59+V60+
V61+V62+V63+V64+V65+V66+V67+V68+V69+V70+
V71+V72+V73+V74+V75+V76+V77+V78+V79+V80+
V81+V82+V83+V84+V85, family="binomial", data=tic.learn)
tic.glm <- glm(V86~V44+V45+V46+V47+V48+V49+V50+
V51+V52+V53+V54+V55+V56+V57+V58+V59+V60+
V61+V62+V63+V64, family="binomial", data=tic.learn)