雑記: 線形回帰モデルが最小 2 乗推定できるにはデータ行列の各列が線形独立

参考文献

  1. 行列が正則であることの意味と5つの条件 | 高校数学の美しい物語(2022年5月5日参照).
    • 5 つの条件が同値であるとある。1. との同値性が一番イメージ的にもわかりやすいのが 4. だと思う。つまり、「正則である(逆行列がある)こととその線形変換の核が原点のみである(原点にうつるのは原点のみである)ことは同値である」ということである。なので自分は 1. と 4. が同値であることを前提にする。
      • ∵ もしある行列に逆行列があるならば、適当なベクトルにその行列をかけてさらに逆行列をかけたとき元のベクトルに戻ってこれなければならないが、原点は線形変換で動かせないので、原点でない点が原点にうつったら元のベクトルに戻れず詰む。なので原点でない点が原点にうつってはならない。
  2. 次元定理の意味,具体例,証明 | 高校数学の美しい物語(2022年5月5日参照).
    • 行列  X \in \mathbb{R}^{n \times m} について   {\rm rank} \, X + {\rm dim}( {\rm Ker} \, X) = m が成り立つ。大学でおぼろげに習ったはずである。
    • さっき「逆行列がある」を「核が原点のみ」にいい換えたが、核がどうだといわれたところでその行列の姿は結局イメージしにくい。なのでさらに核からランクに関連付けるためにこの定理をつかう。そうすると、「逆行列がある」⇔「核が原点のみ」⇔「ランクが列数に等しい」⇔「列ベクトルたちが線形独立である」までつながる。最後の矢印はランクの定義によった。
    • 「列ベクトルたちが線形独立である」までもってくればどのような行列か幾分イメージしやすいと思う。少なくともぱっと反例をあげられる。すべての列ベクトルが同じであるような行列にすればよい。
      • もしデータ行列 X においてすべての列ベクトルが同じであったら、1 つ目の変数にも 2 つ目の変数にも 3 つ目の変数にも同じセンサーの値が記録されているに違いない。


正則化項がない線形回帰モデルの回帰係数が最小 2 乗法で一つに定まるためには、個々のデータを各行に並べた行列  X について X^\top X が正則でなければならない。このための条件は  Xm 本の列ベクトルが線形独立である(つまり、{\rm rank} \, X = m である)ことである。十分性と必要性の証明を下のほうに記す(必要性は 2 パターン)。忙しい人向けに 3 つの証明を 1 行ずつでかくと以下になる。 が正則のいい換えで が次元定理である。
  • X のランクが列数」X の核が原点のみ」⇒「X^\top X の核も原点のみ」X^\top X が正則」
  • X^\top X が正則」X^\top X の核が原点のみ」X^\top X のランクが列数」⇒「X のランクが列数」
  • X^\top X が正則」⇒「X の核が原点のみ」X のランクが列数」

なので、入力空間が 1 次元ならば、つまり m = 1 ならば、すべてのデータが 0 というのでもない限り最小 2 乗法ができる。安心である。

命題.
行列  X \in \mathbb{R}^{n \times m} について、Xm 本の列ベクトルが線形独立である(つまり、{\rm rank} \, X = m である)ことは、X^\top X \in \mathbb{R}^{m \times m} が正則であるための必要十分条件である。
十分性の証明.

正方行列が正則であることと、その行列に対応する線形写像の核が原点のみであることは同値であるので [1]、{\rm Ker} \, X^\top X= \{ 0\} を示せばよい。

まず、次元定理 [2] より、 {\rm dim}( {\rm Ker} \, X) = m - {\rm rank} \, X = 0 なので、{\rm Ker} \, X= \{ 0\} である。よって、 {\rm Ker} \, X^\top X = \{ v \, | \, X^\top X v = 0\, \} \subset \{ v \, | \, v^\top X^\top X v = 0\, \}= \{ v \, | \, X v = 0\, \}={\rm Ker} \, X= \{ 0\}

したがって {\rm Ker} \, X^\top X= \{ 0\} なので X^\top X は正則である。
必要性の証明.
X^\top X が正則であると仮定すると、{\rm Ker} \, X^\top X= \{ 0\} であり、次元定理より {\rm rank} \, X^\top X = m である。
行列の積のランクの性質 {\rm rank} \, X^\top X \leqq {\rm rank} \, X より、m \leqq {\rm rank} \, X である。
他方、 Xn \times m 行列なので {\rm rank} \, X \leqq m でなければならず、結局 {\rm rank} \, X = m である。
必要性の証明(別解).
X^\top X が正則であると仮定すると、
Xv = 0 \; \Rightarrow \; X^\top Xv = 0 \; \Rightarrow \; (X^\top X)^{-1}X^\top Xv = 0 \; \Rightarrow \; v = 0
なので、この対偶をとると、v\neq 0  \; \Rightarrow \;Xv \neq 0 である。よって  \{ v \, | \, X v = 0\, \} = \{ 0\} である。
したがって {\rm Ker} \, X= \{ 0\} なので、次元定理より {\rm rank} \, X = m である。

雑記

お気付きの点がありましたらご指摘いただけますと幸いです。

💜

f:id:cookie-box:20211229152010p:plain:w70

💛

f:id:cookie-box:20211229162343p:plain:w70
  • 参考文献 [1] によると、草の種子の中には、乾燥したままの種子を蒔くよりも、種子を予め低温で湿度が高い環境で保存してから蒔いた方が発芽率が高くなるものがあるのですね? 種子に「いま冬を越えたから発芽しよう(?)」と思わせる効果があると。しかし、[1] の 2 ページ目の架空データの種子は乾燥したまま(control)でもある程度の発芽率はありますね? 彼らは何なんです? 「冬を越えたかわからないけど発芽してヨシ(?)」とでも?
  • 知らないよ。その「何が種子の発芽率に影響を及ぼすのか」を考察するために分散分析モデルをつかおうという話じゃないか。
  • そうですね。[1] のデータを [1] 内のコードでロジスティック回帰すると以下です。なお、germinated 列と not 列は発芽した種子数と発芽しなかった種子数で、2列合わせて今回の被説明変数ですね。そして、treatment 列が低温湿潤処理(stratification)をしたかどうかで、condition 列は明るい環境(light)だったか暗い環境だったかです。
  • data <- read.delim("data.txt")
    fit <- glm(
        cbind(germinated, not) ~ treatment*condition,
        data=data,
        family=binomial(link="logit")
    )
    print(summary(fit))
    
    Deviance Residuals: 
        Min       1Q   Median       3Q      Max  
    -2.1007  -1.0798  -0.1452   0.5999   3.0857  
    
    Coefficients:
                                           Estimate Std. Error z value Pr(>|z|)    
    (Intercept)                             -2.3403     0.2904  -8.059 7.67e-16 ***
    treatmentstratification                  1.8508     0.3356   5.515 3.49e-08 ***
    conditionlight                           1.9969     0.3352   5.958 2.56e-09 ***
    treatmentstratification:conditionlight  -0.4957     0.4180  -1.186    0.236    
    ---
    Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
    
    (Dispersion parameter for binomial family taken to be 1)
    
        Null deviance: 184.738  on 23  degrees of freedom
    Residual deviance:  42.253  on 20  degrees of freedom
    AIC: 126.28
    
    Number of Fisher Scoring iterations: 4
    
    print(anova(fit, test="Chisq"))
    
    Analysis of Deviance Table
    
    Model: binomial, link: logit
    
    Response: cbind(germinated, not)
    
    Terms added sequentially (first to last)
    
    
                        Df Deviance Resid. Df Resid. Dev  Pr(>Chi)    
    NULL                                   23    184.738              
    treatment            1   58.901        22    125.837 1.658e-14 ***
    condition            1   82.143        21     43.694 < 2.2e-16 ***
    treatment:condition  1    1.441        20     42.253    0.2299    
    

雑記

以下の Pipfle と Pipfile.lock から pipenv を install すると fast_transformer はインストールできた。ただし fast_transformer 以外のパッケージもごちゃごちゃ入っている。

ML-on-WSL/Pipfile at f9600f6a5d8e44257b31d428e2cbce7514269744 · CookieBox26/ML-on-WSL · GitHub
ML-on-WSL/Pipfile.lock at f9600f6a5d8e44257b31d428e2cbce7514269744 · CookieBox26/ML-on-WSL · GitHub

$ pipenv install
$ pipenv run python
>>> import fast_transformers.causal_product.causal_product_cuda


あと上記のリポジトリには pytest にコードのはぎれを置いてあるが通しで実行すると tensorflow 系のテストが通らない。個々のテストファイルだけを実行すると通る。pytest ではまれによくある。

 tensorflow.python.framework.errors_impl.FailedPreconditionError: Failed to allocate scratch buffer for device 0

雑記

昨日の記事で以下を実行できるようになったが、なぜ PyPI から pipenv で入れたときは動かなかったのか、pipenv で fast_transoformers は管理できないのか。

$ python
>>> import fast_transformers.causal_product.causal_product_cuda


適当なディレクトリに pipenv 環境を構築し、pytorch-fast-transformers を PyPI からインストールし、~/.local/share/virtualenvs/ 以下をみてみる。causal_product.causal_product_cpu しかない。causal_product.causal_product_cuda が import できないのは当然である。実際 _cuda は import できず _cpu は import できる。

$ pipenv install pytorch-fast-transformers
$ ls ~/.local/share/virtualenvs/20220502_sandbox-j2IpnJRo/lib/python3.8/site-packages/fast_transformers/causal_product/
__init__.py  __pycache__  causal_product_cpu.cpython-38-x86_64-linux-gnu.so


先の pipenv 環境を一旦削除し、今度は pytorch-fast-transformers を GitHub からインストールする。と、今度は PyTorch が必要だと怒られるので先に PyTorch を入れる。→ ことをしたかったが Pipfile の Lock が終わらない。

$ pipenv install "https://download.pytorch.org/whl/cu115/torch-1.11.0%2Bcu115-cp38-cp38-linux_x86_64.whl"
$ pipenv install git+https://github.com/idiap/fast-transformers.git#egg=pytorch-fast-transformers
$ ls ~/.local/share/virtualenvs/20220502_sandbox-j2IpnJRo/lib/python3.8/site-packages/fast_transformers/causal_product/