ホーム » 画像解析
「画像解析」カテゴリーアーカイブ
Feature Importanceを知る
世の中ではやはり解釈性が重要らしいです。
前回、SHAP含めてモデル解釈の指標についていくつか触れました。やはり一度では僕は残念ながら理解できないので復習も含めて今回この記事を書きます。
前回の復習
上記のリンク先が前回の記事になります。- Permutation Importance
- Partial Dependence
- LIME
- SHAP
ちなみに他にもDrop-Column Importanceとかもあるらしいです。
Feature Importance
順番的には逆になってしまいましたが、決定木自体にはFeature Importanceというものがあります。ご存知ですよね。どうやって算出されてるのや?と思ったので調べました。結論から言えばあまりにも式が複雑で完全に理解し切るのはかなりハードです。。なのでその計算の核となるGini Impurityから始めます。
Gini不純度

はクラスの総数
はクラスiの割合
二郎系 家系 まぜそば各クラスから均等な量の場合とあるクラスに偏りがある場合
count = 4 4 4
p = 4/12 4/12 4/12
= 1/3 1/3 1/3
GI = 1 - [ (1/3)^2 + (1/3)^2 + (1/3)^2 ]
= 1 - [ 1/9 + 1/9 + 1/9 ]
= 1 - 1/3
= 2/3
= 0.667
二郎系 家系 まぜそば少し小さくなりました。ではあるノードにおいて単一のクラスのみある場合はどうでしょうか。
count = 3 3 6
p = 3/12 3/12 6/12
= 1/4 1/4 1/2
GI = 1 - [ (1/4)^2 + (1/4)^2 + (1/2)^2 ]
= 1 - [ 1/16 + 1/16 + 1/4 ]
= 1 - 6/16
= 10/16
= 0.625
二郎系 家系 まぜそば0となりました。きれいに分類できている証拠ですね。決定木のFeature ImportanceはこのGiniを用いて算出されているようです。 参考文献によると
count = 0 12 0
p = 0/12 12/12 0/12
= 0 1 0
GI = 1 - [ 0^2 + 1^2 + 0^2 ]
= 1 - [ 0 + 1 + 0 ]
= 1 - 1
= 0.00


つまり、対象の特徴量が木全体においてどれだけGini不純度の減少に寄与できたかという指標でFeature Importanceが算出されているということです。
ということはです。分岐点を多く作りやすい変数の方が相対的にFeature Importanceが大きくなるのは直感的ですよね。単純に考えるとカテゴリカル変数よりも連続値変数の方がFeature Importanceが相対的に高まってしまうということです。さらに木を深めることで多くの分岐点が生成されるのであればその効果は莫大です。
実際Feature ImportanceにはCardinalityが密接に関係します。次にCardinalityについてみてみます。
Cardinality
みんな大好きKaggleにおいて次のような質問があった。

ここでカーディナリティとは、対象の変数の多様性のこと。つまり性別のようなカテゴリカル変数よりは連続値の変数の方がカーディナリティは相対的に高い。
これはまさに上記のGiniの定義より得られた考えのことだ。よってさきほどのFeature Importanceに対する理解は正しかったということだ。
Information Gain
実は決定木における重要な指標はGini Impurityだけではなく、Information Gain(平均情報量)というものが別であります。
LIME
じゃあ、どうしたらちゃんとした、まともな、直感的なFeature Importanceが得られるのか。という問に対する答えは僕の知るベストだとSHAPだ。もうSHAPしかない。上述した理由から決定木におけるFeature Importanceに信憑性はない、結果的に重回帰がやはり好かれている。しかし、分類という点においては決定木やNNには重回帰では残念ながら勝てない。
最高に分類できる状態を保ちつつ、重回帰のように最高の形でFeature Importanceがほしい、という欲求を満たしてくれるのがSHAPだ。LIMEの上位互換なのでやってることはほぼ同じ。
記事の最後になりましたがここでは低次元空間においてLIMEの振る舞いを簡単に実装してSHAP(LIMEの上位互換)のイメージを理解します。下のような非線形データを考えます。




ちなみにSHAPの凄いところは制約3つめのConsistencyです。これによって対象の特徴量のFIがより重み付されます。これによって決定木におけるFIの相対的なつぶれよりも直感的なFIを得ることができます。
Reference
- https://jamesmccaffrey.wordpress.com/2018/09/06/calculating-gini-impurity-example/
- https://en.wikipedia.org/wiki/Decision_tree_learning#Gini_impurity
- https://mlcourse.ai/articles/topic5-part3-feature-importance/
- https://towardsdatascience.com/the-mathematics-of-decision-trees-random-forest-and-feature-importance-in-scikit-learn-and-spark-f2861df67e3
- https://medium.com/coinmonks/what-is-entropy-and-why-information-gain-is-matter-4e85d46d2f01
- https://datascience.stackexchange.com/questions/10228/when-should-i-use-gini-impurity-as-opposed-to-information-gain
モデル評価 入門
本日は機械学習のモデルの評価方法についてまとめます。Gistsがかなり重くなってしまったので一発で見れない場合はColabで開くか、Gistsに飛んだのちページを何度か更新してみてください。
分類指標
この記事では分類問題に焦点を当てます。なので回帰におけるMSEとかは話しません。- TP / TN / FP / FN (真陽性 / 真陰性 / 偽陽性 / 偽陰性)
- confusion matrix (混同行列)
- simple accuracy (正解率)
- recall (再現率) (sensitivity)
- precision (適合率)
- f1 measure (F値)
- f1 beta measure (重み付きF値)
- threshold (閾値)
- ROC / AUC (受信者操作特性 / AUC下部の面積)
- MCC (マシューズ相関係数)
分類指標の必要性
もちろん、汎用性がめちゃくちゃ高いものがあればそれでいいんですが残念ながら私は知らないです。。。他にも具体例で考えてみましょう。たとえば、100枚のラーメンの写真をデータセットとします。モデル

- 二郎系だ
- 二郎系ではない



Confusion Matrix
クラス分類の結果をまとめた表のこと。各要素がTP / TN / FP / FNとなる。ただし、これは二値の場合。しかし多値分類でも同様に作れます。

Accuracy
もっとも、シンプルかつ、直感的な正答率
Precision
少しの外れを許すが機会損失したくない時に使う
Recall (Sensitivity)
機会損失してでもとにかく正確に当てたい時に使う
PrecisionとRecallの具体例
たとえば全国の二郎系を制覇したいという目的に対してはRecallよりもPrecisionを重視します。なぜならば行ったラーメン店が高い確率で二郎系あっても素通りしてしまっては目標が達成できないからです。逆にRecallを重視するのはたとえば病気を判別するときです。病気なのに病気ではない、と判断すると大変ですよね
とはいえ、完璧な分類は共に高いのでどうせならこの二つの指標を同時に見たいですよね。つまり。2つの指標を同時に加味して「全体としての良さ」を測りたい時に

F1 measure
RecallとPrecisionを同時に考慮する指標です。調和平均という見方もできますが


F-beta measure
RecallとPrecisionに重みを加えたF measureです。いわば一般化です。

Recallを重視したいなら (



![Rendered by QuickLaTeX.com w_1 \in [0,1]](https://research.miidas.jp/wp-content/ql-cache/quicklatex.com-68bb507dd59c93a6e06505c0011aa48e_l3.png)
![Rendered by QuickLaTeX.com w_2 \in [0,1]](https://research.miidas.jp/wp-content/ql-cache/quicklatex.com-70c5a075787512d2f3ebdc8d1943b7ec_l3.png)

van Rijsbergen’s E (effectiveness) function
F-measureは実は別の指標から導出されたものらしいです。起源は次のもの

代入して変形します。


![Rendered by QuickLaTeX.com R, P \in [0,1]](https://research.miidas.jp/wp-content/ql-cache/quicklatex.com-2179d1d0770c262db344b01b88238f2c_l3.png)














とはいえ、わかったことをまとめると直感的な加重調和平均は




ROCとAUC
確率出力に対して最もいい閾値を見つけると同時に、モデルを比較するための指標をグラフ化したものです。グラフ上の点は特定の閾値を用いてラベリングされたのちの混合行列から算出されたspecificity, sensitivityである。次の動画がかなりわかりやすいので絶対見てください。
簡単にまとめると、例えばロジスティック回帰を用いた2値分類を考えます。この時に閾値をいくつにするかが問題ですよね。出力の確率と閾値を比較して大きければ1,小さければ0のようにラベルを振る必要があるからです。つまり実数からカテゴリカルに変換する必要性。
ということはです、もちろん閾値と混合行列は一対一対応します。
どの閾値がもっともいい分類をしてくれるのか?という問に答えてくれるのがROCです。
そしていくつかのモデルに対してどのモデルがいいか、つまりどのROCがいいかという問に答えてくれるのがAUCです。

そして上の図中の点ですが、これひとつひとつが特定の閾値によって算出された混合行列を用いて計算されたTPR、FPRです。
ここでわかったこととして他クラスのROCはそう単純ではないということです。sklearnに実装はありますがバイナリ で実装されているのか閾値をクラス数で分割しているのかわかりませんが、理論上はそう簡単にROCが作れないことは気にかけておいた方がいいと思います。
MCC
各クラスのサイズが非常に異なっていても使用できる評価指標です。この記事の冒頭で極端な例をあげましたが、実世界の分析においてはよくあることだと思います。ですのでその点ではいい指標だなと思います。


SHAP値で解釈する前にPermutation ImportanceとPDPを知る
昔、kaggleから宿題メールみたいなものが届いたんですよね。


ブラックボックス
機械学習も僕の知っている2年前に比べて色々と賑やかになってきました。決定木だとLightGBMやXGBOOSTありますし、ニューラルネットだとStacked LSTMやGANとかですねえ。そんな優秀なアルゴリズム達をどうやって理解すればいいんだろう?と言うのがブラックボックス問題です。例えば「ニューラルネットで学習させたけどこの重みの意味って、、、?」とか「この入力と出力の間の関係は、、?」とか「この変数って予測にプラスに働いたのか、、、?」などです。この記事ではそんなブラックボックスを少しでも理解するための方法をまとめます。
Permutation Importance
例えば決定木だとFeature Importanceがあります。これはモデルが使用する特徴量の重要度を数値化したものです。アルゴリズムに関してここでは触れませんがPlotはこんな感じです。

Partial Dependence Plots
上でどの特徴量が重要か分かりました。ではその特徴量と出力の間の関係知りたくなりますよね?そこでpartial dependence plotの登場です。参考文献にあるLINEさんのスライド見てあまりにも感動したんです。なんでかと言いますとこのアルゴリズムは選択した特徴量以外を周辺化で消すんですよね、その周辺化がまさに積分なんです。ベイズで出てくる周辺分布と同じようなことをしてるんです。

ではプロットを見てみます。データはirisです。

- x軸は変数の値
- y軸はbaseline(一番左の点)との予測(prediction)の比較
- 青枠は信頼区間
SHapley Additive exPlanations Value

LIME
SHAPアルゴリズムについてはLIMEというものがベースとなっているようです。


SHAP
話が少しそれましたがSHAPのアルゴリズムに移ります。これが非常に難しかった。。論文中にある「Simple Properties Uniquely Determine Additive Feature Attributions」の部分が肝です。LIMEに制約を設ける感じです。





これ以上は全くわからないのですいません、説明はここまでします。ここでは使えるようになることに集中します。
- https://github.com/slundberg/shap
- https://arxiv.org/abs/1602.04938
- https://papers.nips.cc/paper/7062-a-unified-approach-to-interpreting-model-predictions.pdf



横軸が目的変数の値で縦軸が特徴変数の貢献度の高さです。赤が正の値を、青が負の値となります。例えば、s5は目的変数が大きく(右側)なるほど赤い分布となり、目的変数が小さく(左側)なるほど青い分布となります。つまり、目的変数とs5は正の相関があることがわかります。


Reference
- https://www.kaggle.com/dansbecker/permutation-importance
- https://speakerdeck.com/line_developers/machine-learning-and-interpretability
- http://alfredplpl.hatenablog.com/entry/2013/12/24/225420
- http://maruo51.com/2019/05/02/feature_importances_/
- https://dropout009.hatenablog.com/entry/2019/01/07/124214
- https://qiita.com/shin_mura/items/cde01198552eda9146b7
- https://slundberg.github.io/shap/notebooks/plots/dependence_plot.html
- https://www.slideshare.net/SatoshiHara3/ss-126157179
ハイパラ最適化に困ってるんやろ?Optunaやで
久しぶりに欲しいものができたんですよね。無印の「軽量オーストラリアダウンポケッタブルマフラー」なんですけどオンラインでも全部在庫がないみたいで入荷を心待ちにしています。
そんなことはおいておいて、本日はハイパーパラメータ最適化についてです。
ハイパーパラメータとは
ハイパーパラメータの前にパラメータがありますよね、違いはなんでしょう?LassoとRidgeを例に取りましょう。上の記事で解説したのでそちらもみていただきたいのですが、モデルを定義する際に学習させる変数がありますよね。よく






これでパラメータとハイパーパラメータの違いが理解できたと思います。真相学習や機械学習の問題の一つはこのハイパーパラメータの最適化です。例えばニューラルネットワークにおいて活性化関数に何を使うかや決定木において深さをどうするかめっちゃ悩みますよね?それを最適化したいんです。
Grid Search
よくある手法の一つがグリッドサーチです。これは格子状にハイパーパラメータの候補を作り、総当たりしてその結果を見てハイパーパラメータを選ぶという手法です。sklearnにあるのでみてみましょう。Optuna
あの最強のPreferred Networks, Inc.さんが開発しました。Optuna はハイパーパラメータの最適化を自動化するためのソフトウェアフレームワークです。ハイパーパラメータの値に関する試行錯誤を自動的に行いながら、優れた性能を発揮するハイパーパラメータの値を自動的に発見します。現在は Python で利用できます。これがすごいんです。論文にもなったようです。
Optuna は次の試行で試すべきハイパーパラメータの値を決めるために、完了している試行の履歴を用いています。そこまでで完了している試行の履歴に基づき、有望そうな領域を推定し、その領域の値を実際に試すということを繰り返します。そして、新たに得られた結果に基づき、更に有望そうな領域を推定します。具体的には、Tree-structured Parzen Estimator というベイズ最適化アルゴリズムの一種を用いています。

使い方






- https://papers.nips.cc/paper/4443-algorithms-for-hyper-parameter-optimization.pdf
- https://www.slideshare.net/hskksk/hyperopt
- https://pythonoum.wordpress.com/2018/09/09/parameter-tuning/
- https://qiita.com/kenchin110100/items/ac3edb480d789481f134

Code
References
Softmaxを数式から実装まで
本日は待ちに待ったソフトマックス回帰の実装です。ロジスティックの兄さんのような存在のロジスティック。出力が確率の多値分類になっただけです。この記事では数式をゴリゴリ計算していこうと思います。
Softmax function







参考
- https://en.wikipedia.org/wiki/Softmax_function
- https://www.kdnuggets.com/2016/07/softmax-regression-related-logistic-regression.html
- http://ufldl.stanford.edu/tutorial/supervised/SoftmaxRegression/
- https://math.stackexchange.com/questions/1428344/what-is-the-derivation-of-the-derivative-of-softmax-regression-or-multinomial-l
- https://houxianxu.github.io/2015/04/23/logistic-softmax-regression/
物体検出をとりあえず
僕が初めて書いた比較的まともなコードって多分物体検出なんですよね。物体検出、つまりObject Detectionとはなんぞや、の方のために以下の画像を用意しました。
非常に難しそうに思えるかもしれませんが、単一種類の物体検出ならとても簡単です。cv2というライブラリを使いましょう。今私は単一の、と言いました。これは例えば人の顔であったり、犬の顔であったりします。もう少し深くいうと、人の顔(正面)、人の顔(横顔)などもあります。そしてこれらはカスケードファイルという形で保存されています。これは機械学習でいう所の正解ラベルのようなものです。このカスケードファイルには色々な種類があります。 例えば上のリンクを見てもらうと多種多様なカスケードファイルがあることがわかります。つまり、オリジナルのカスケードファイルを作ればオリジナルの物体検出ができるということです。カスケードの自作は可能ですがどうやら少し難しいようです。機会があれば記事にしたいと思っています。リンクを一応貼っておきます。
- Creating a Cascade of Haar-Like Classifiers: Step by Step
- Tutorial: OpenCV
haartraining (Rapid Object Detection With A Cascade of Boosted Classifiers Based on Haar-like Features) - Creating a haar cascade classifier aka haar training
- Making your own Haar Cascade Intro – OpenCV with Python for Image and Video Analysis 17
物体検出はやっていて楽しいので自分への課題としてFlaskを使った簡単なサービスをできないかなと思っていたりします。しかし、サーバーなどの知識があまりないのですぐにとは行きそうにないです。。。なのはともあれコードを見ましょう。の前に1つだけ注意です。opencvを使うとエラーが頻繁に起こります、実際に次のコード内でもおきています。しかし、ほとんどの原因はPATHです。なのでフルパスで渡すか、今回の場合はwebのurlで作動しなかったのでwgetコマンドを使ってダウンロードして同じディレクトリ上にファイルを置くことで解決しました。このへんは注意してください。また、Pythonの仕様かMacの仕様かはわかりませんがplt.imshowにおいて画像の色が反転してしまうのでRGBを変更するコマンドを忘れないように注意してください。

- scaleFactorは小さいほど検出が正確になる
- minNeighborsは大きいほど検出が正確になる
CNNの目的関数の考察と歴史
こんにちは。
久しぶりの投稿になりました。本日の内容はタイトル通りです。
線形回帰とかの目的関数って最適解を持ちましたね。
しかし、ニューラルネットワークはそうはいかないと言いました。
つまり、目的関数が凸関数ではない可能性が非常に高いんですね。
目的関数や凸関数、勾配法がわからない方は次の記事をみてください。
CNNの目的関数を可視化した論文があります。
その図をお借りして実際にどんな感じか見てみましょう。
skip(residual) connectionとはResNetの特徴であるResidul blockの恒等写像のことです。
ちなみにこれは余談ですが、ResNetとXGBって考え方似てると思いませんか?
見ての通り左は明らかに凸ではないですね、右もマシではありそうですがサドルポイントが見られます。
別の図も見てみましょう。次のはCIFAR-10 datasetの学習の際のプロットになります。
すごくないですか?何がってskip connectionのおかげで少し凸っぽくなってます。
VGGとDenseNetは初見なので調べてみました。というかいろんなモデル多過ぎ、、、
この際なのでニューラルネットワークのモデルをちょろっとみてみましょう。
そもそも現在流行りのCNNの基盤となったアルゴリズムはLeNet-5というものです。
開発者はフランス人のYann LeCun’s Home Pageです。
僕も最近知ったんですがこれ何がえぐいかって1998年に発表されているんです。
1998年ですよ?、どんな時代かググってみました。
パソコンの歴史/年代流行によると
1. Windows98発売
2. アップルが初代iMacを発売
だそうです。まだちょっとすごさがわからないので調べてみると
– Windows 98 – Virtual x86
– What’s iMac – AirMac
だそうです。言いたいことは今のスマホの足元に到底及ばないスペックです。
まあこの話は置いておいて、VGGとDensenetは僕は初見だったので調べてみました。
まずはVGGです。下のアーキテクチャは論文のものです。
2014年のアルゴリズムで当時はかなり深いとされていたようです。
それほど喋ることが見当たらないのですが強いていうなら
このモデルのアウトプットベクトルが1000なので1000種類の画像を識別できます。
Fine Tuningすればあなたの好みの画像を分類できます。例えば、好みの女優とか?
なんでモデルを最初から作らずFine Tuningするのか?
という問に対する答えは、学習量が減るからのようです。
具体的には元々のモデル上層部の重みは学習データを変えてもそれほど変化しないようなので
そのまま使い下層部つまり出力層に近い重みを更新するようです。
入力が人からキリンとかになったらどうかと思いますがね、、、
続きまして、DenseNetです。
これはResNetの改良版と言えるでしょう。改良版というのは次のようにResNetを問題視したからです。
An advantage of ResNets is that the gradient can flow directly through the identity function from later layers to the earlier layers. However, the identity function and the output of H` are combined by summation, which may impede the information flow in the network.
そもそもResNetの背景には深層における勾配消失問題があります。
この対策としてidentity functionが導入されResNetができたのですがDenseNetでは
それはメリットである一方、モデルにおける情報フローを阻害していると考えたようです。
言われてみるとそうかも知れませんね。そこで考えたれた
ResNetの特徴Residul blockに対するDense blockです。見ての通り前工程の出力を全て入力に使っています。
で、使われたモデルはこんな感じで
ResNet含め、その他のアルゴリズムとの比較結果がこれ
青の数値がDenseNetです。エラーが小さいのでいい精度であることがわかります。
長くなりましたがいろんなCNNと目的関数の凸性を見てみました。
ちなみにこれら全てkerasにあります。
– Applications
便利な時代ですね。。。。そしてこれらも勾配法使われていると思うとエグい、、、
でわ。
READMORE
ねぇPython、CNNって何?(理論編 Part-1)
本日からはニューラルネットワークweek。最新のものまで突っ走りましょう。
てゆーか、ニューラルネットワークってなんだったっけ?
入出力数とか層数などは気にせずこんな風にニューロンを使った関数がニューラルネットワークでした。そして層が比較的深いものを多層パーセプトロンといいました。よく見ると
入出力がベクトル
になっていますね。いいんです。実際データなんてベクトル形式なんです。各学生のテストのデータも、競馬のデータも株価も終値とかを横並びにしてベクトルです。
しかーーし!
これ今日僕がとって虹なんですけど。こんな風に画像を入力としたい場合はベクトルじゃなくないですか?実際サイズは(691 × 502)ですし、しかもRGBなんです。RGBはレッド・グリーン・ブルーの略です、つまり3次元。
この画像のニューラルネットワークの入力として使いたいとするとこのままだと無理なので作戦を考える必要があります。
- とりあえずグレースケールにする(RGBからモノクロ)
こうするととりあえずデータのシェイプ(横,縦,奥)がになります。しかしまだ行列のままなのでもう一工夫
- 各行を横に並べて
のベクトルにするもしくは縦に並べたベクトルにする
こうすることで画像をベクトルとして扱えるようになりました!わーい
それは無理やりすぎる
ごもっともです。行列をベクトルにするなんて邪道すぎますね。行列入力できるニューラルネットワークが
畳み込みニューラルネットワーク(Convolutional Neural Network)
なんです。そう、画像に特化したニューラルネットワーク。
けどどうやって行列入力可能にしたんや?
その前に、そもそもなんで画像をベクトルとして扱うべきでないかというと
たとえばこの画像、四角で囲ったところを1ピクセルだとします。ここだけ見ても何もわからなくないですか?というのはこのピクセルから学習できそうなことはあるのか?ということです。一方で
こう見るとどうですか?虹がハッキリと映っていてさっきよりは意味あるピクセルになっていますよね、つまり、コンピューターが画像を学習するには今までのようなベクトルの要素単位ではなくもっと大きな範囲を1単位として見る必要があるからです。それが
畳み込み
なんです。この場合だと真ん中の行列がコンピューターの目となりKernel matrixといったりします。これをずらしていって手前の出力を作るんですがとりあえず一気に定式化します。
- 入力シェイプは
フィルタ数: K
フィルタサイズ: F
スライド幅: S
パディング: P - 出力シェイプは
フィルタサイズとはKernelサイズのこと、スライド幅はフィルタのずらし幅、パディングは画像の縁に新たなピクセルを組み込むことzero-paddingがメジャー。これは縁に0ピクセルを付け加えること、こうすることで
- 縁の畳み込み回数が増える
- パラメータの更新数が増える
- カーネルのサイズを調節できる
などのメリットがあります。
そして出力のシェイプで分母にとありますがこれについては次の図を見てください。緑が入力、オレンジが出力
スライド幅: 1
スライド幅: 2
緑のブロックにカーネルを重ね合わせ線型結合を計算します。この際、スライド幅が適切でないシェイプが少数になるのでそこだけ注意。
CNNでは畳み込みに加えてPoolingという操作があります。これは画像の縮小です。今までのニューラルネットワークでは隠れ層のノード数を減らすことで次元を落としていました。これを行列入力においても可能にしようというものです。
具体的な方法はMax-poolingというものです。のKernelでスライド幅2だと次のようになります。
定式化すると
- 入力:
フィルタサイズ: F
スライド幅: S - 出力:
となります。しかし、Poolingという操作はあまり人気がないらしいのでスライド幅の大きい畳み込みで対処するようです。
最後に次のリンクが非常に参考になるので見てみてください。
本日はここまでです。でわ。
ねぇPython、PCAって何?(実装編+)
こんにちは。では前回の内容を踏まえて空間を変えないPCAを行いましょう。今回使うのは
顔のデータ
各次元4096で400サンプル。これを空間を保ち64次元に落とす。つまり4096次元の空間で64本の固有ベクトルがはる空間へ射影する。
これでPCAは一件落着。
ニューラルネットワークに深入りしていく予定。
でわ。