glmnetで多クラスのロジスティック回帰

誰かやってるようでなかったのでメモ。
glmnetはElastic Net(L1で罰則つけるlasso回帰、L2で罰則つけるリッジ回帰のまぜあわせ)ができるパッケージで、こいつを使うと多クラスのロジスティック(多項ロジスティック)回帰もできる。

まずパッケージを突っ込む。

install.packages("glmnet")
library("glmnet")

ここでは定番のirisデータで、3値クラス分類をやってみる。xはdata.frameではなく行列しか受け付けない、めんどいが型変換が必要。

x <- as.matrix(iris[,-5])
y <- iris[,5]

実行結果は載せないが、デフォルトだと罰則の強さλを適当に複数の値(グリッド)で割り振って回帰した結果が返ってくる。またデフォルトではラッソ・リッジの混ぜ込み具合であるパラメータαが1になっており、ラッソ回帰になる。結果出てくるモデルの係数を取るにはcoef関数を指定する。type.multinomialは、各クラス(Species, setosaとか)ごとに推計されるパラメータにおいて、ない場所(0となる箇所)を同じに揃えてくれるというオプション。更に、family引数を調整すれば多クラスのロジスティック以外、例えば通常のロジスティック回帰(binomialにする)も実行できる。

coef(glmnet(x, y, family="multinomial"))
coef(glmnet(x, y, family="multinomial", type.multinomial="grouped"))


罰則の強さλは考えてもしょうがないんでクロスバリデーション(CV)で決めちゃおうってのが、cv.glmnet関数。そして、最適(デフォルトがlambda.1seになってるが意味がわからん)なλで予測するのがpredict関数だ。ここでは分類結果(class)を返させているが、type引数をいじると各クラスに所属する確率(response)やらも返してくれる。

cvfit <- cv.glmnet(x, y, family="multinomial", type.multinomial="grouped")
pred <- predict(cvfit, newx=x, type="class")


もとのデータをどのくらい正しく分類できているのかを見て見ると、結構いい感じだ。

> table(pred, iris[,5])
            
pred         setosa versicolor virginica
  setosa         50          0         0
  versicolor      0         47         1
  virginica       0          3        49

参考

いろいろみたけど結局、vignetteが一番よかった(Multinomial Modelsの箇所)。