2
1

More than 3 years have passed since last update.

機械学習パッケージmlrを使った順序関係があるカテゴリ分類(その1)

Last updated at Posted at 2020-07-08

1.はじめに

仕事では順序関係があるカテゴリ分類のデータを扱うことが多いので、Rのmlrパッケージを使った機械学習にチャレンジしてみました。
ちなみに、仕事はIT関係では全くないので、全くの素人分析屋です。

1.1mlrについて

Rでは機械学習のパッケージとしてcaretが有名ですが、mlrもよく使われているみたいです。mlrについてはcaretよりも情報が少ない感じがしますので、備忘録代わりに、少しずつ投稿していこうと思っています。
まずmlrについては、下記の参考記事を見てください。 
 Rの機械学習パッケージmlrのチュートリアル(タスクの作成から予測まで)

2.データの準備

順序関係があるカテゴリ分類として、package(mlbench)にある米国ボストン市郊外における地域別の住宅価格のデータセットを変形してみたいと思います。
始めに必要なパッケージをインストールしておきます。

library(ranger)
library(mlr)
library(mlbench)

data(BostonHousing, package = "mlbench")
df = BostonHousing

データの概要
crim: 町ごとの一人当たりの犯罪率
zn: 25,000平方フィートを超える区画に分けられた住宅地の割合。
indus: 町あたりの非小売業の割合(面積比)
chas: Charles River dummy variable (= 1 路が川と接している場合; 0 その他).
nox: 窒素酸化物濃度(1000万分の1)
rm: 住居あたりの部屋の平均数
age: 1940年より前に建てられた所有者が居住するユニットの割合。(データセットの調査年度が1978年)
dis: 5つのボストン雇用センターまでの距離の加重平均
rad: 環状高速道路へのアクセシビリティのインデックス
tax: 10,000ドルあたりの固定資産税率
ptratio: 町別の生徒-教師比率
black: =1000(Bk-0.63)^ 2, ここでBkは、町の黒人の割合。
lstat: 人口に下層クラスが占める割合(%)
medv:所有者が居住する住宅の中央値(\ $ 1000s)

df$medvC = cut(df$medv,breaks = 3,labels = c(1,2,3))
table(df$medvC)

$>  1   2   3 
$>215 243  48 

さて、通常はmedvを目的変数とした回帰モデルになるのですが、今回はmedvを3クラスのカテゴリーに分けました。
今回の解析の目的はクラス分類で、特にクラス3を判別させたい動機があるとします。
クラス3は48と他のクラスと比べて少なくなっています。
また、クラス(1,2,3)には順序関係があります。

3.タスクの定義

まずタスクを定義します。
タスクとは問題の概要をまとめたオブジェクトのことで、問題の種類や、扱うデータセットに関する情報が含まれます。
最初に、train data とtest dataに分けます。
7割をtrain dataとして残りをtest data にします。
train.setは後で同じものを使うので保存しておきます。

set.seed(123)
n = nrow(df)
train.set = sample(n, size = n*0.7)
test.set = setdiff(1:n, train.set)
write(train.set,file = "train.txt")

ターゲット(目的変数)は分類の場合、factorでなければいけないため、factor化してからタスクの定義をします。
分類の場合はmakeClassifTask()、回帰の場合はmakeRegrTask()を使います。

df$medv = NULL
df$medvC = as.factor(df$medvC)
task_BostonHousing = makeClassifTask(id = "BostonHousing", data = df, target = "medvC")
task_BH_train = subsetTask(task_BostonHousing ,subset =train.set )
task_BH_train

$>Supervised task: BostonHousing
$>Type: classif
$>Target: medvC
$>Observations: 354
$>Features:
$>   numerics     factors     ordered functionals 
$>         12           1           0           0 
$>Missings: FALSE
$>Has weights: FALSE
$>Has blocking: FALSE
$>Has coordinates: FALSE
$>Classes: 3
$>  1   2   3 
$>144 181  29 
$>Positive class: NA

訓練データの概要を示しました。
説明変数にfactorsが一つ入っていますが、後は全てnumericsとなっています。
欠測値もありません。
クラス分類は、やや不均衡クラスとなっています。

4.学習器の構築

学習器はmakeLearner関数で作成します。
このとき、どのような学習手法を使うのかを指定します。加えて以下の要素を指定できます。

ハイパーパラメータの指定
予測後の出力方法(例えば、分類問題において予測されたクラスラベルなのか、確率なのか)
ID(いくつかの手法ではこのIDを出力やプロット時の名前として利用できる)

まず、ランダムフォレスト(ranger)でモデルを作成してみます。
Permutationベースの変数重要度をみるために、importanceをpermutationに指定します。

set.seed(123)
classif.lrn= makeLearner(  "classif.ranger",importance="permutation")

4.ハイパーパラメータのチューニング及びリサンプリング

ハイパーパラメータのチューニングのための方法を指定します。
makeParamSetを使います。
mtryはintegarなのでmakeIntegerParamを用います。
そしてグリッドサーチ法を用います(makeTuneControlGrid)。
リサンプリングの手法は(makeResampleDesc)7分割のクロスヴァリデーションを指定します。

mlrではmakeResampleDesc関数を使ってリサンプリング手法を設定する。
この関数にはリサンプリング手法>の名前とともに、手法に応じてその他の情報(例えば繰り返し数など)を指定する。サポートしているサンプリング手法は以下のとおりである。
CV: クロスバリデーション(Cross-varidation)
LOO: 一つ抜き法(Leave-one-out cross-varidation)
RepCV: Repeatedクロスバリデーション(Repeated cross-varidation)
Bootstrap: out-of-bagブートストラップとそのバリエーション(b632等)
Subsample: サブサンプリング(モンテカルロクロスバリデーションとも呼ばれる)
Holdout: ホールドアウト法

ランダムフォレストには作成する決定木の数(ntree)と、1つ1つの決定木を作成する際に使用する特徴量の数(mtry)の2つのパラメータがありますが、ここでは、決定木の数(ntree)は固定して、特徴量の数(mtry)をパラメータをグリッドサーチ法でチューニングします。

ps = makeParamSet(makeIntegerParam("mtry", lower = 1, upper = 13))
ctrl = makeTuneControlGrid(resolution =  13)
rdesc = makeResampleDesc("CV",iters = 7)
rdesc

$>Resample description: cross-validation with 7 iterations.
$>Predict: test
$>Stratification: FALSE

5.パラメータのチューニングの実行

設定が終わりましたので、tuneParamsを使って、チューニングを実行します。
モデルの評価関数は順序型クラス分類なのでkappaを指定します。
mlrではparallelMapパッケージで並列処理を実行できます。

library("parallel") #detectCores()を使ってCPUコア数を取得する
library("parallelMap")
set.seed(123)
parallelStartSocket(detectCores())
res = tuneParams(classif.lrn, task = task_BH_train, resampling = rdesc, par.set = ps, control = ctrl,measures = kappa)
parallelStop() #parallelStart~で並列処理が始まり、parallelStopで止める

$>Starting parallelization in mode=socket with cpus=8.
$>[Tune] Started tuning learner classif.ranger for parameter set:
$>With control class: TuneControlGrid
$>Imputation value: 1
$>Exporting objects to slaves for mode socket: .mlr.slave.options
$>Mapping in parallel: mode = socket; level = mlr.tuneParams; cpus = 8; elements = 13.
$>[Tune] Result: mtry=11 : kappa.test.mean=0.7013263
$>Stopped parallelization. All cleaned up.

6.チューニングした結果を学習器にセット

チューニングの結果は、mtry=11のときに、クロスバリデーションによるベストがkappaは0.70となりました。
setHyperParsを使って、学習器にハイパーパラメータ(mtry=11)をセットします。

classif.lrn = setHyperPars(classif.lrn, par.vals = res$x)

7.訓練データを用いた学習器の訓練

早速、訓練データを使ってモデルを作成します。

fit = train(classif.lrn, task_BH_train)

8.テストデータの作成

モデルの評価をするため、訓練に用いていないテストデータを作成します。

testTask = subsetTask(task_BostonHousing ,subset =test.set )
testTask

$>Supervised task: BostonHousing
$>Type: classif
$>Target: medvC
$>Observations: 152
$>Features:
$>   numerics     factors     ordered functionals 
$>         12           1           0           0 
$>Missings: FALSE
$>Has weights: FALSE
$>Has blocking: FALSE
$>Has coordinates: FALSE
$>Classes: 3
$> 1  2  3 
$>71 62 19 
Positive class: NA

テストデータは152のデータでクラス1とクラス2がほぼ同数、クラス3が他のクラスの半分以下の構成になっています。

9.予測の実行と評価

pred = predict(fit, testTask)
performance(pred,measures = kappa)
calculateConfusionMatrix(pred,sums = T)

$>    kappa 
$>0.6910121 
$>        1  2  3 -err.- -n-
$>1      57 14  0     14  71
$>2       9 52  1     10  62
$>3       0  4 15      4  19
$>-err.-  9 18  1     28  NA
$>-n-    66 70 16     NA 354  

ランダムフォレストによる判別分析のテストデータによる検証結果は、kappaは0.69です。通常、kappaは0.6を超えると分類性能は良いとされるので、まずまずの結果です。
クラス3誤分類率は4/19=0.21、偽陽性率は1/16=0.06となりました。偽陽性率は低いですが、誤分類率が2割であるため、全てのクラス3を補足することがやや難しいです。

さて、次回もさらにモデルの検討を進めてみます。
機械学習パッケージmlrを使った順序関係があるカテゴリ分類(その2)

10.参考

mlrパッケージチュートリアル - Quick Walkthrough編

 

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1