琥珀色呑んだくれ備忘録

メモとか備忘録とか

[感想]『自然科学研究のためのR入門』

まずは、本書を御恵贈いただき、あらためて著者に感謝したい。あくまで感想文として、この本を教科書として、同僚(特に若い方)やカウンターパートと仕事を共有するうえで、自分ならどのようなポイントに注意するかに焦点を絞ってコメントしたい*1

全体

対象としない読者

  • ご自身ではデータ分析とレポート作成をしないポジションのかた
  • このご時世でも『研究の再現性は不要』と思ってるひと
  • 『再現可能なレポート』について精通しているRユーザー
  • Rによるデータ分析自体の習得を目指しているかた

上記以外は必読。ただし、研究責任者としてご自身ではデータ分析に従事しない立場であっても、こうした技術的に解決できる枠組みを検討せず、対策を講じていないままという態度は無責任といえよう。

www.kyoritsu-pub.co.jp

測定した、シミュレーションした、あるいはカウンターパートから預かったデータを分析するのが、(特に自然科学の)研究者の日常的な活動のひとつ*2

言い尽くされていることではあるが、報告した結果を元のデータから再現できることは、データ分析者にとっての最良の自衛手段であり義務でもある。その立場と目的にたって、本書は研究者や学生が『再現可能なレポート』を書くために、必要なステップと今の技術を最速で習得するための一冊になっている *3

COI

著書をご恵投いただく程度には交流がある。

1章:RmarkdownとRstudioを使う

Rによるデータ分析結果を報告するという目的上、報告以前のデータ分析の知識はある程度は持っていることが前提。

引用文献リストの自動取り込み方法も触れられている。引用文献リストの掲載がひとつもないレポートは研究報告には値しないので*4*5、この作業の定型化と省力化は研究報告の作成時には非常に重要なポイントとなる。類書ではあまり最初に出てこないが、本書ではこれが1章でカバーされており、ツールの選定・検討中の研究者には嬉しい。

本書の特色として、各章にsession_info()の出力が付けられている。報告相手が別の環境でレポートの再現を試みることを想定して、分析環境の情報共有も重要なポイントといえる。 自分以外の人に、結果(あるいはデータ分析がうまく行かない)を相談したり、報告内容を再現してもらう際にしばしばトラップとなる*6

2,3,4章:統計モデリング、実験計画法と分散分析を使った分析とレポーティング

これらの各章では、データの分析をstep-by-stepで実施しながら、一通りの分析が終わった時点でレポートが出来上がっているという流れになっており、Rmarkdownの嬉しさが最大限に発揮されるポイントのひとつといえるだろう。

これ以降の章では、一連の分析風景を追いかけてくれているので具体的なイメージを持ちやすい。 機械学習などによる分析や自身で提案した新しい分析手法を報告する際にも、既存の方法をベースラインとした対比が必要となる*7。 データ分析に際して、どのような順番でどのような方法でアプローチしていくか、あるいはそれぞれの分析において着目すべきポイントや勘所が随所にちりばめられており、著者の経験に基づいた実践的な知識の一端に触れることができるのも楽しい。

5章:機械学習(など)を使った分析のレポーティング

冒頭でごく簡単に、Bioconductorからのパッケージの導入にも触れている。本書の読者には、実験から解析までこなすバイオインフォマティシャンも多く想定され、分析風景がより身近になるのではないだろうか。

再現性の観点から、欲を言えば、機械学習の方法には乱数を利用するものも多いため*8set.seed()で乱数を固定する方法は紹介されても良かったかなと思う *9 *10

最近は、初期検討として機械学習の各種手法を横並びに比較をすることも多く、メタフレームワークのひとつであるcaretを使った学習パラメタのチューニング・性能評価と比較方法の紹介はありがたい *11 *12

また、xgboostのパラメータチューニングについては、全自動でやってくれるautoxgboostもあるので薦めておきたい。

kato-kohaku-0.hatenablog.com

AUCROCによるパフォーマンスの比較について

ROCが三角形になっていて気になった*13。これは予測ラベルを直接投入しているためと思われるが、各症例の予測値や検査値をもとにROCをみながらカットオフの検討をしてる業界などでは、この図で報告すると戸惑われる可能性がある *14

たとえば、random forestのラベルの得票率とlassoの回帰の値をそれぞれ投入して、両者を比較したらよかったのではないかと思う *15

require(randomForest)
require(glmnet)
require(pROC)

data(spam, package = "kernlab")
# glimpse(spam)

X <- spam[, -NCOL(spam)]
y <- as.factor(spam[,  NCOL(spam)])

train <- sample(1:NROW(spam), NROW(spam) * 0.7)
test  <- setdiff(1:NROW(spam), train)

# train learner + predict test with random forest
rf <- randomForest(X[train, ], y[train], ntree=500)
pred.rf <- predict(rf, X[test, ], type="prob")
head(pred.rf)
#>    nonspam  spam
#> 4    0.026 0.974
#> 24   0.296 0.704
#> 30   0.082 0.918
#> 32   0.078 0.922
#> 33   0.236 0.764
#> 34   0.844 0.156

# tune-train learner + predict test with lasso
cv <- cv.glmnet(x = as.matrix(X[train, ]), y = as.numeric(y[train]))
lasso <- glmnet(x = as.matrix(X[train, ]), y = as.numeric(y[train]), lambda = cv$lambda.1se, alpha = 1)
pred.lasso <- predict(lasso, as.matrix(X[test, ]))
head(pred.lasso)
#>          s0
#> 4  1.481061
#> 24 1.529340
#> 30 1.899370
#> 32 1.652855
#> 33 1.592823
#> 34 1.532178

# prot ROC
roc.rf <- roc(response = y[test],             predictor = pred.rf[,1])
roc.la <- roc(response = as.numeric(y[test]), predictor = c(pred.lasso))

mt <- sprintf("RF(red) vs lasso(blue) = %.3f vs =%.3f",auc(roc.rf),auc(roc.la))
plot.roc(roc.rf, col = "red",  main = mt)
plot.roc(roc.la, col = "blue", add = TRUE)

f:id:kato-satoshi-0:20181013115315p:plain

6章:集大成

この章では、レポートの提出を強く意識する*16 報告相手に次第では、コード部分や処理途中の出力などはノイズでしかなく、場合によってはレポートそのものを見てもらえないこともある *17。重要なポイントと思った。

結論:(Rで)データ分析をしている研究者には必携の書

  • 報告の必要がなくても、手元の分析結果をレポートの形で残す習慣を身に着けたい
  • R以外で分析をするユーザーを対象とした書籍が出てくれると良い。

www.kyoritsu-pub.co.jp

*1:献本を遣り取りする文化から転職して既に長いため、書評のようにきちんと精査したものではないことは、ご容赦されたい。

*2:純粋な理論系は違うかもしれないが..

*3:必要最低限の情報提供にとどめることで、常々忙しい忙しいとか多言する研究者に取捨選択をさせないスタイルになっているが、各章末に発展内容への適切なガイドを付けることでカバーされている

*4:少なくとも自然科学の研究者にとって

*5:ただの作業記録やポエムならともかく

*6:報告書の作成時には見落としがちであるが、OSが違ったり、分析に必要なパッケージが入ってなかったり、使っているパッケージがバージョンアップでオプションの指定方法が変わったり、出力されるデータの構造が変わったりすることがある

*7:情報学系なら事情が異なるかもしれないが、自分の業界では査読で必ず突っ込まれる

*8:例えば本書でも取り上げられているrandom forestなど

*9:特に初学者が再現を試みたときに結果の数字が元のテキストと違っていると戸惑うことが多い

*10:一意な乱数に固定することで、報告対象にチャンピオンデータを誘導したりネガティブな結果を隠蔽しかねない悪用や弊害があるのは承知している

*11:自分はmlRユーザーなのでcaretはあまり常用してないけど、事情はそれほど変わらないだろう

*12:ついでながら、expand.grid()は、caretじゃなくてbaseの関数だけど、実践的には困ることはないだろう

*13:情報系の論文では見るので、目的に応じるのだと思う

*14:誰に報告するかといった業界や事情の違いがあるので、あくまで個人的な体験に基づく

*15:手元のデータでパパっとやったので、本書のデータでの解析例ではないことはご容赦されたい

*16:include=FALSE や echo=FALSE といったチャンクオプションを使いながら、適宜、隠蔽する方法が示されており、分析者が手元で再現できれば良い、あるいは、付録として分けるといった説明がされている。

*17:このあたりは、どういう相手かに応じて分ける必要がある