Turing.jlで欠損値付きデータに対して線形回帰を行う

はじめに

Suyamaさんのブログ*1で,データに欠損値がある場合の教師あり学習について説明されています.本記事では,そちらの記事及びソースコード*2 を参考に,欠損値が含まれるデータに対して線形モデルを仮定し, 欠損値と重みをTuring.jlで推論します.またSuyamaさんのブログと同様に,欠損値が含まれるデータを省いて学習を行ったもの,欠損値を推定しながら学習を行ったもの,欠損値がないデータで学習を行ったもので結果を比較してみました.

Turing.jl*3はJulia用のProbabilistic Programmingライブラリで,確率モデルを定義し,推論方法を指定するとパラメータに対する推論を自動で行ってくれます.

実験設定

2次元実数ベクトルxと実数yの組みの集合が与えられ,線形モデルのパラメタwを推定したいとします.ただし,xの要素は適当な確率で欠損が発生しています.線形モデルを次のように定義します.ただし, \lambda_y, \mu_x, \lambda_x, \mu_w, \lambda_{w}はハイパーパラメータです.

\begin{align*}
    P(y_n | x_n, w) = \mathcal{N}(y_n | w^\mathrm{T}x_n, \lambda_y)\\
    P(x_{n,d}) = \mathcal{N}(x_{n,d} | \mu_x, \lambda_{x})\\
    P(w_d) = \mathcal{N}(w_d | \mu_w, \lambda_{w}) 
\end{align*}
このモデル,入力データ,及びその欠損情報をTuringで記述します.本来Turingでは入力データに欠損が混じってていても内部的に処理して推論してくれる機能が想定されているようなのですが*4,どうやらバグ*5*6がでているようで,欠損が混じったデータをそのまま入力しても上手く動きませんでした.現状,欠損を分離して記述する必要があるようです.予測モデルは次のように記述しました.モデルの実装にあたって,Stanで実装されていたこちらの記事*7を参考にさせて頂きました.

@model function linear_regression_with_miss(x1, x1_miss, x2, x2_miss, y, N1, N2, N3, N4)
    # hypter paramteters
    mu_x = 0
    lambda_x = 1.5
    lambda_w = 100
    lambda_y = 1
    
    nfeatures = 2
    W ~ MvNormal(nfeatures, lambda_w)
    
    # no missing
    for i in 1:N1
        mu = x1[i] * W[1] + x2[i] * W[2] 
        y[i] ~ Normal(mu, lambda_y)
    end
    
    # only x1 is missed
    for i in N1+1:N1+N2
        x1_miss[i-N1] ~ Normal(mu_x, lambda_x)
        mu = x1_miss[i-N1] * W[1] + x2[i] * W[2] 
        y[i] ~ Normal(mu, lambda_y)  
    end
    
    # only x2 is missed
    for i in N1+N2+1:N1+N2+N3
        x2_miss[i-N1-N2] ~ Normal(mu_x, lambda_x)
        mu = x1[i-N2] * W[1] + x2_miss[i-N1-N2] * W[2] 
        y[i] ~ Normal(mu, lambda_y)  
    end
    
    # both x1 and x2 are missed
    for i in N1+N2+N3+1:N1+N2+N3+N4
        x1_miss[i-N1-N3] ~ Normal(mu_x, lambda_x)
        x2_miss[i-N1-N2] ~ Normal(mu_x, lambda_x)
        mu = x1_miss[i-N1-N3] * W[1] + x2_miss[i-N1-N2] * W[2]
        y[i] ~ Normal(mu, lambda_y)  
    end
end

実験

データ数 Nを30, xの要素を50%の確率で欠損にしたデータを用意します.このデータは上で定義した予測モデルのハイパーパラメータの値を少し変えたものからサンプリングしています.NUTSでサンプリングし,得られた結果を可視化したものが次の図になります.f:id:tetuppei:20201028184155p:plain横軸と縦軸が x_1,  x_2の各要素の大きさ,丸い点が各 x,点の色が yの大きさを表しています. また,等高線が学習した wによる予測値になります.図は左から,欠損値があるデータを省いて学習を行ったもの,欠損値を推定しながら学習を行ったもの,欠損値がないデータで学習を行ったものになります.中央の図のx印が欠損値の平均値,青い帯が欠損値の不確実性を表しています.

3つの図の等高線を比較してみると,定性的な比較ではありますが,この例では,欠損値を推定しながら学習を行ったものが(真中の図), 欠損値が含まれるデータを省いて学習を行ったものよりも(左図), 欠損値がないデータで学習を行ったもの(右図)に近い結果になっていることが分かります.

感想

欠損値推定について

もちろん,上のような結果が常に得られるわけではなく,データセットの数や分布, 欠損率の値次第では, 欠損したものを省いても結果がほとんど変わらない場合もありますし,極端な事前分布を仮定すると違った結果が得られます.実データを解析する際は,無理のない範囲で事前分布を設定するのが良いのだろうと思いました.

Turing.jlについて

まだ,発展途上な感じはしますが,Turing.jlはかなり良いライブラリだと感じました.僕のPPLの知識はStanを少し触ったことがある程度のものなのですが,モデルの記述自体は全然苦労しませんでしたし,Juliaでデータ解析をするのであれば,純正のライブラリということで,インストールからデータの受け渡しまでスムーズでした.欠損値推定の機能なんかもすごく便利だと思います.

付録

実験に使ったjupyter notebookはこちらで公開しています.
https://github.com/tetupei/my_blog/blob/main/src/linear_regression_with_interpolation.ipynb

PEAKを読んでみた

www.amazon.co.jp

 

この本は研究者の著者がチェス、バイオリン、数字の暗記等の様々な分野におけるトッププレーヤを研究し、超一流を作り上げた練習方法の知見をまとめたものである。特に、deliberate practicemental representationという2つの概念が印象に残ったので、それらについてまとめておく。

deliberate practice

筆者は二種類の練習方法、naive practicedeliberate practiceについて説明し、自分の技術を向上させるためにはdeliberate practiceが不可欠であると主張している。naive practiceとは意図がなく、ただ回数をこなすだけの練習を意味し、いくらこの練習を行っても上達が見込めない。例えば、ピアノの練習でいうと、長時間同じ曲を引き続けたり、テニスでいうとただ単に素振りをするということである。ある研究報告では、20 ~ 30年間のキャリアを積んだ医者は、医大を卒業して2 ~ 3年のキャリアの医者よりも、特定の観点でみると腕が悪いと場合があると報告されている。これは、naive practiceでは、能力を維持することすら難しいということを意味している。

その一方で、deliberate practiceとは明確なゴールに向けて、集中的に訓練する練習を意味する。結局、この練習方法を継続的に行えるか否かが、一流と二流の分水嶺となっているようだ。実際に、この練習を取り入れることで、数字の暗記競技において最高記録を更新したり、ゴルフのスコアが良くなったりといくつもの成功事例が報告されている。

deliberate practiceとは以下を満たすような練習である。

  1. 明確な目標が設定されている
  2. どこが良くて、どこが悪いのかのfeedbackが得られる
  3. 挑戦的である(comfort zoneから外れている)

1. 明確な目標が設定されている

例えば、ピアノの曲をあるスピードで、ミスを3回以内におさえて弾くというように、その練習が成功したかどうかを判定できるように設定する必要がある。

2. どこが良くて、どこが悪いのかのfeedbackが得られる

errorがあることが分かっても、どこがどう悪いのか分からないと改善することができない。この観点において、上級者からfeed backを得ることはとても有益である。

3. 挑戦的である(comfort zoneから外れている)

この観点が最も重要で、自分自信ができないことに挑戦する必要がある。自分自信ができる事をやり続けても決して成長しない。

 mental representations

mental representationsを鍛えることが、deliberate practiceの質を高めるために重要であると主張している。mental representationsとは物体、抽象的な物体(例えばアイデア)に対する精神構造を意味する。例えば、モナリザという言葉を聞いた時、頭の中に一枚の女性の像が浮かぶと思うが、その像がモナリザに対するmental representationである。ある人は、ぼんやりした像しか想像できないが、他方、鮮明ではっきりとした像が浮かぶ人もいるだろう。このmental representationの質が、プロとアマチュアでは異なる。例えば音楽のプロは、良い音に対するはっきりとした感覚をもっているため、自分自信の練習においても優れたfeedbackを得ることが出来る。一方、初心者のmental representationは貧弱であるため、間違った音を弾いても、気付くことができない。mental representationは、deliberate practiceを行うことで、その質を高めることができる。逆にmental representationを高めることで、deliberate practiceの効率も上がっていく。

感想

この本は僕にとってかなりのヒット作で、読んだのは1年半ほど前なのだが、一人で読みながら「なるほど!」と何度もつぶやく位おもしろいと感じたことを覚えている。僕はかつて、どこかで聞いた1万時間の法則を盲信していて、がむしゃらに練習時間を増やしていたことがあったが、後から振り返ってみると、あまり意味がなかった場合が多いと感じていたし、やはり質が大事だということをこの本で知れたことが有り難い。効率の良い学習に興味を持っている全ての人におすすめできる一冊です。