データサイエンティスト上がりの経営者のブログ(仮)

データ駆動、統計学、データ分析、機械学習、AIなどについて書いてます

データサイエンティストからCDOへ

今年でiAnalysis社(アイアナ)を立ち上げてからちょうど10年経ちました。分析事業を大きくしたいと思って活動していたものの、資金調達などはできずに、結局は自分個人のコンサルティングに終始した10年でした。そういう意味ではうまくいかなかったなと思うものの、ちょうど今年から、クレディセゾン社のCDO(Chief Data Officer、最高データ責任者)に就くことになりました。セゾンへは去年からデータ分析のアドバイザーをしています。

 

セゾンのアドバイザーをする前は、ドコモ社に何年かコンサルティングをしていました。ドコモのデータ分析部署の立ち上げ時に協力し、顧客のLTV(Life Time Value)の開発をしたり、顧客体験の分析などをしていました。このときのドコモの部長に誘って頂いた勉強会でセゾンの役員と知り合い、アドバイザーをすることになりました。セゾンではいくつかのプロジェクトを見て、データの活用方法を改善することで、すぐに成果を出すことができ、CDOをオファーされた形です。いまもセゾン社内のいろんなチームを見ています。

 

自分はもともとデータサイエンティストと呼ばれることに抵抗感がありました。データサイエンティストと言うと、すべてについてデータを根拠にしないと許せないようなイメージを感じ、自分は違うのになと。むしろ、よく対比される勘と経験の方がしっくりくるタイプ。抽象的な絵も描くし麻雀やスロットなども好きで、アーティストな性格の方が合います。ドコモのプロジェクトが終わった後、何年か、絵を描きながら自分のやりたい事を考えていました。

 

アイアナを作ったのは、自分で事業をやりたいからで、それは今も変わってません。いつか大きい事業をやりたい。ただ、特に事業のネタがあるわけじゃない今、仕事として自分がやりたい事は何かなって考えると、経営者をやりたいなというところに行きつきました。それからは周りの人にアドバイスをもらいながら事業について考えつつ、セゾンで成果を出し、CDOになることができました。データサイエンティストはしっくりこないとは思いつつも、大学やコンサルで長年経験を積んできた専門分野ではあるので、それを活かして経営側に関わることが出来るのはとても有り難く感じています。個人的にはこれからの大企業を良くしていきたい、ひいては日本を良くしたいという思いもあります。CDOの役割を果たしつつ、経営者としての能力を磨き、日本の今後に少しでも役立てたらと思っています。

 

 

 

医療分野から学ぶベンチマーク分析の有用可能性

ビッグデータ、データサイエンス、AIなどのブームによって、データを扱ったりエビデンスを作ることがビジネスに大きな貢献をもたらすことは社会的に合意されてきてきました。データを扱うことは統計学が基礎になっていて、統計学は医療分野で最も発展してきました。AIでさえ基礎となる考え方は統計学です(基本は回帰分析やA/Bテスト)。

 

その医療分野で、エビデンスのレベルが階層化されています(wikipediaから引用)。

f:id:isseing333:20200610111556p:plain

 

この内容をビジネス的に読み替えると、1〜2段目の実験や症例報告は個人の経験や知見、3〜4段目の症例対照研究やコホート研究は調査データや社内DBの分析、ランダム化比較試験はA/Bテスト、になります。ここまではやられている企業はすでに相当増えていると思います。

 

その次のエビデンスは、医療ではメタアナリシスになっています。これは、複数の分析結果(論文)の内容をとりまとめて、さらに分析をすることです。ビジネスでは、複数の調査結果や複数の企業のデータをとりまとめることになると思われます。自社のデータを既に分析しつくした場合、次に欲しくなるのは同業他社のデータや分析ではないでしょうか?ベンチマークとも言われる分析です。ビッグデータやデータ統合が進んできたら、そのようなことも可能になってくるでしょう。

 

一番上はガイドラインとなっており、これはエビデンスというよりはエビデンスの結果作られる業界水準になるでしょう。実質、データから生み出される最大のエビデンスベンチマークとなり、今後ビジネスで活用されていくことが期待されます。

疫学の始まり:ジョン・スノウのコレラ研究とデータの重要性

久しぶりにブログを書きます。コロナが広まり、なんとか被害を少なくするために、疫学という学問が活用されています。疫学は医療系のデータを扱う統計学で、1800年代にジョン・スノウという研究者の研究が始まりと言われています。私は東京大学の健康科学科と大学院時代に専攻していました。

 

イギリスでコレラが流行したとき、コレラがどうして起こるのか何も分かっていませんでした。空気感染じゃないかと言われていましたが、同じ地域に住む人でも非感染者がいることに疑問をもち、ジョン・スノウは汚い水を飲むとコレラにかかるのではないかという仮説を立てました。そして実際に汚染した水を飲んでいる家庭のデータを集めたところ、コレラにかかっている家庭と一致したため、行政がこの結果をもとに汚い水を供給している井戸を閉鎖し、コレラが収束したと言われています。

 

コレラの菌が発見されたのはそれから30年後で、原因がわからなくても、解決ができたということになります。正しくデータを集めて正しく分析すれば、ロジックが分からなくても十分な問題解決ができるということが、統計学(疫学)の強力なポイントです。

 

ジョン・スノウは仮説を立ててデータを集めましたが、現代はIT化によってさまざまなデータが溜まっています。それを正しく分析すれば、仮説が十分でなくてもいろんなことが分かります。もちろん医療だけでなくビジネスでもデータは活用できますし、企業の経営判断や、コレラのときのように政治判断にも影響するでしょう。私はこれまでさまざまな企業にコンサルして業績に関わるような分析結果を出してきましたが、今後さらにデータを活用する機会が増えていくのではないでしょうか。アフターコロナ時代でも、データがさらに重要になっていくと思われます。

 

異常検知について

この本を読みました。

いろんな場合でどんな手法があるかが書いてあるので、とても整理されています。

まとめると、

  • 1次元で山がひとつの異常検知:ガンマ分布で異常度を計算する
  • 多次元または山が複数ある異常検知:クラスタリング
  • 不要な次元を含むデータからの異常検知:主成分分析による異常検知
  • 目的変数のある異常検知:リッジ回帰
  • 周期のわかる時系列データの異常検知:自己回帰モデル
  • 周期のわからない時系列データの異常検知:部分状態空間モデル

って感じです。
多くの場合は、クラスタリングと主成分分析異常検知でまかなえます。

時系列異常検知のできる部分状態空間モデルは魅力的ですが、本によるとRのパッケージは充実してないみたい。要調査。

ggplot2でロジスティック回帰の近似曲線を描く

バージョンアップで昔の指定方法ができなくなってた。
調べたら下記のようにやれば描ける。ggplot2は綺麗なんだけど仕様変更が多いから困る。

binomial_smooth <- function(...) {
  geom_smooth(method = "glm", 
              method.args = list(family = "binomial"), ...)
}

ggplot(data, aes(x, y)) + geom_point() + binomial_smooth()

メモ:ROC曲線の最適カットオフを計算する関数

epiライブラリのROC関数ではカットオフまで計算してくれなかったので、ROC関数を計算するように書き換え。

library(epi)

ROC1 <- function (test = NULL, stat = NULL, form = NULL, plot = c("sp", 
    "ROC"), PS = is.null(test), PV = TRUE, MX = TRUE, MI = TRUE, 
    AUC = TRUE, grid = seq(0, 100, 10), col.grid = gray(0.9), 
    cuts = NULL, lwd = 2, data = parent.frame(), ...) 
{
    rnam <- if (!missing(test)) 
        deparse(substitute(test))
    else "lr.eta"
    if (is.null(form)) {
        if (is.null(stat) | is.null(test)) 
            stop("Either 'test' AND 'stat' OR 'formula' must be supplied!")
        lr <- glm(stat ~ test, family = binomial)
        resp <- stat
        Model.inf <- paste("Model: ", deparse(substitute(stat)), 
            "~", deparse(substitute(test)))
    }
    else {
        lr <- glm(form, family = binomial, data = data)
        resp <- eval(parse(text = deparse(form2)), envir = lr$model)
        Model.inf <- paste("Model: ", paste(paste(form)[c(2, 
            1, 3)], collapse = " "))
    }
    m <- as.matrix(base::table(switch(PS + 1, test, lr$fit), 
        resp))
    m <- addmargins(rbind(0, m), 2)
    fv <- c(-Inf, sort(unique(switch(PS + 1, test, lr$fit))))
    nr <- nrow(m)
    m <- apply(m, 2, cumsum)
    sns <- (m[nr, 2] - m[, 2])/m[nr, 2]
    spc <- m[, 1]/m[nr, 1]
    pvp <- m[, 2]/m[, 3]
    pvn <- (m[nr, 1] - m[, 1])/(m[nr, 3] - m[, 3])
    res <- data.frame(cbind(sns, spc, pvp, pvn, fv))
    ddaattaa <- data.frame(lr[21], lr$fit)
    names(res) <- c("sens", "spec", "pvp", "pvn", rnam)
    auc <- sum((res[-1, "sens"] + res[-nr, "sens"])/2 * abs(diff(1 - 
        res[, "spec"])))
    
    mx <- max(res[, 1] + res[, 2])
    mhv <- which((res[, 1] + res[, 2]) == mx)
    mxf <- fv[mhv]
    
    cutoff <- ddaattaa[ddaattaa$lr.fit == mxf, ]
    
    invisible(list(res = res, AUC = auc, lr = lr, cutoff = cutoff, optimal = res[mhv, ], 
                   n = nrow(ddaattaa), freq = table(ddaattaa[, 1])))
}

b <- ROC(form = a[, 1] ~ a[, 2], plot="ROC")
c <- ROC1(form = a[, 1] ~ a[, 2], plot="ROC")
c$cutoff
c$AUC
c$optimal
c$n
c$freq