Matlabユザコミュニティ

MATLAB & 金宝appSimulinkユ,ザ,コミュニティ,向け日本語ブログ

MATLABとPythonの違いとは:PythonでKaggleに参加し,3位に入賞したMathWorks社員が感じたこと

今回はテクニカルコンサルタントの池田さんに,Kaggleで入賞したお話しを聞かせて頂きます!


こんには。MathWorks Japanでデ,タ分析のテクニカルコンサルタントをしている池田です。今回,初めてmatlabブログに投稿させていただきます。今後も不定期で投稿させていただきたいと思いますので,よろしくお願いします!

さて,タイトルにもありますように,2022年6 ~ 10月に開催されたKaggleの医療画像認識コンペ(梅奥诊所- STRIP AI)で,3位に入賞しました!3.位という結果は望外の出来事で、運がよかったというのが正直な感想です。とても学びの多かったコンペで、楽しく参加させていただきました。このような素晴らしい機会を提供して頂いた Mayo Clinic 様には感謝感謝です。

さて,本記事では,“MATLABとPythonの違い”にいて述べたいと思います。私はMathWorks社員なのですが,今回のKaggleコンペティションにはPythonで参戦しています。コードコンペティション(PythonかRのコード自体を提出する形式のコンペ)だったからというのが,その理由です。日中はMATLABで仕事,プラベトはPythonでKaggle。そんな日々を送っていると,改めて見えてくるんです,“MATLABとPythonの違い”が。

MATLABとPythonは良く比較されるプログラミング言語だと思います。プログラミングを始めようとしている方の中には,

“MATLABとPython,どっがいい?”」

と思っている方も多いでしょう。もろん,この問いに対する普遍的な回答はありません。MATLABには MATLAB の、Python には Python の良いところがあるからです。

私はもともとMATLABが大好きなのですが(だからMathWorks社員をしています),Pythonも好きでよく使います。KaggleはPythonで参戦することが多いですし,仕事でもお客様のご要望でMATLAB連携のためにPythonを書くこともあります。そんなわけで,MATLABとPythonの両方を良く知っているエンジニアを自負しています。

この記事では,Kaggleのコンペでの具体的な体験を通じて,MATLABとPythonの違いについて,筆者が感じたことを率直に述べてみたいと思います。

もろん,この記事で述べているのは,一人のMathWorks社員の一の見方です。ですが,本記事が" MATLABとPythonは何が違うのか?という疑問を持っている方への一助になれば幸いです。

コンペティションの内容と入賞した解法

本題に入る前に,今回私が参加したコンペの概要と解法にいて紹介させてください。梅奥诊所- STRIP AIは,病理画像の画像分類を行うコンペティションです。デジタルパソロジ,と呼ばれる病理画像から,脳卒中の血栓の原因を分類するというタスクです。画像を入力とし,CE(心脏栓塞;心原性)と大动脉粥样硬化;アテロム血栓性)のいずれであるかを推測します。いわゆる2クラス画像分類問題です。

今回のコンペは,2の点で特徴的でした。

  1. 入力画像が巨大なため,前処理を工夫する必要がある
  2. 判別の難易度が高く,どれが"良い判別モデル"なのかを特定するのが難しい

巨大画像に対する前処理:补丁提取

今回のコンペの入力画像は,とにかく巨大でした。ファ▪▪▪▪▪▪▪▪▪▪▪▪MBから数gbもあります。こんな巨大な画像を直接ディ、プラ、ニングモデルに入力することはできません!それどころか,馬鹿正直に画像をメモリ上に読み込もうとすると,メモリ不足になってKaggleの内核が落ちるという事態が発生します。とにかく前処理が重要なコンペティションでした。

私が採用した前処理は,matlabブログのこらの記事で紹介されていたものと同様の方法です。巨大な画像を小さいパッチ画像に分割し,モデルの入力とするというものです。下図は,前処理の概略を示した図です(前記matlabブログの記事から引用)。

病理画像のPatch Extraction (MATLABブログより引用)

一般に,大きな画像をディープラーニングの入力とする場合,モデルの入力サイズと合うように画像を縮小することが多いです。ですが,本コンテストのように巨大な画像を縮小してしまうと,微細なテクスチャが消えてしまい,識別率が悪くなることがあります。そこで,今回の手法のように,画像を縮小せずにパッチ状に切り出せば,細かいテクスチャを失わずに識別モデルに入力できるというわけです。恐らく,多くのコンペ参加者がこの手法をとったのではないかと思います。

モデルの精度を正しく測るという難しさ

今回のコンペ,とにかくタスクが難しかったです。画像がceかlaaかを判別する2値分類なのですが,どう頑張っても精度がでない!3位入賞した私のモデルも,ランダムな推測より若干良いという程度の精度でした。簡単に過学習してしまい,むしろランダム推測より精度が悪くなることもしばしば。このため,”何が良いモデルなのか”をいかに正確に判断してモデルを改善するかが本コンテストの肝だったように思います。

モデル精度の最も簡単な測り方は,Kaggleの公共排行榜を見ることです。公众排行榜とは,コンペ開催中に開示される暫定ランキングのことです。コンペ参加者が判別モデルを提出すると,テストデータの一部を用いて精度を算出し,精度が高い順のランキングが公開されます。コンペ参加者はこのランキング表の数値を見て,モデルを試行錯誤します。ただ,今回のコンペでは暫定ランキングの算出に使われるサンプル数が少なく,公共排行榜があまりあてになりませんでした。この点に留意せず、公共排行榜の数値を追いかけると,少量のデータに過適合した汎用性のないモデルになってしまいます。私自身,過去に同じ失敗をしたことがありましたので,今回のコンペでは公共排行榜を完全に無視しながらモデルの改善を行いました。安易に目の前の数字を信頼するな,ということですね。

モデルの精度を測る方法はもう一あります。それが交叉验证です。学習データをモデル学習用と精度検証用に分割することで,モデルの学習と精度の測定を同時に行う方法です。今回のコンペでは、公共排行榜のサンプル数より学習データのサンプル数の方が圧倒的に多かったので,交叉验证(交差検証)の方がより信頼度の高い精度測定法でした。

では,交叉验证の精度をそのまま鵜呑みにすればよいのか?実はそうではありません。“学習デ,タの分布”に留意する必要があるからです。今回の学習デ,タではceとlaaがだいたい7:3で分布していました。タスクの難易度が高い場合,画像から有効な特徴量をなかなか抽出できません。すると,モデルは“学習デ,タの分布”自体を重要な手掛かりとして判別ル,ルを構築してしまいます。つまり”,入力画像のだいたい7割をCE、だいたい3割をLAAと判別する”ように学習してしまいます。

もちろん,実世界のCE: LAAの割合が7:3なのであれば問題ないのですが,もし,実世界の分布が5:5だったら吗?2:8だったら?学習されたモデルの精度は壊滅的なものになってしまいます。今回のコンペでは,まさにこれが起こりました。多くのコンペ参加者が“交叉验证では精度が良いが,実際のテストデータでは精度が悪い”という経験をしたのではないでしょうか。

今回のコンペで最終的に私がとった方法は,”类体重で学習データの分布の偏りを補正した上で,交叉验证の数値が良くなるようにモデルを試行錯誤する”というものでした。类体重を用いることで,学習データの偏りに依存しないようにモデルを学習・評価できます。そのうえで、公共排行榜ではなく,より信頼度の高い交叉验证のスコアを見てモデルの良し悪しを判断しました。

MATLABでは,交叉验证は分类学习者App回归学习者Appで簡単に使うことができます。また,班级重量に関しても,ClassificationOutputLayerのClassWeightsプロパティでサポ,トしています。

第三名解决方案の概略

最終的な私の解法を簡単にご紹介します。

まず,モデルの学習時の処理にいてご説明します。前述したとおり,画像デ,タは全て事前にパッチ状に分割します。その後,モデルの预培训をまず行います。今回,私はResNet152V2等の事前学習済みのディープラーニングモデルを使いましたが,これらのモデルはImageNetという自然画のデータで学習されたモデルです。自然画と病理画像では性質が大きく異なると考えましたので,学習前に训练的“処理を挟みました。今回のコンペでは,学習用の训练数据集に加え,本タスクとは異なるラベルが付与された病理画像が其他数据集として配布されていました。このを其他数据集用いてモデルを训练的“し,その後,训练数据集を用いてモデルの学習を行いました。なお,モデルの学習時には,前述した类别权重を使いました。使用したモデルは,ResNet152V2, EfficientNetB0, Xceptionです。

推論(学習したモデルで予測を行う)時は,学習時と同様に入力画像をパッチ状に分割し,学習したモデルで推測を行います。各パッチに対して各モデルの推測値を計算し,その平均をとることで最終的な予測値としています。

MATLABとPythonの違いを実感した凡ミス

さて,前置きが長くなってしまいましたが,ここからが本題です!今回,PythonでKaggleコンペに参加したのですが,実は私の作成したPythonコードにバグがあり,貴重な時間を3日間もロスしてしまうというミスをしてしまいました。ここからは,私がPythonで犯したミスについて説明しつつ,この出来事から感じた“MATLABとPythonの違い”について語りたいと思います。

百聞は一見に如かず,ということで,私が書いたPythonコ,ドの一部をまず紹介します。このコードは,入力画像の前処理を行うコードの一部です。(説明のため,実際のコードから一部変更しています)1行目と2行目はライブラリの読み込みです。3行目は,pyvipsを使って画像を読み込んでいます。入力画像は非常に巨大なので,画像全体をメモリに読み込むことができませんので,巨大画像を少ないメモリで扱うことができるpyvipsを使っています。4行目で,巨大画像をパッチ状に切り出しています。5行目で,パッチ状に切り出した画像をメモリ上にロードし,pythonのnumpy配列として展開します。6行目で,openCVのラaaplブラリを使って,imageをout.tifに保存します。

进口pyvips
进口cv2
image = pyvip . image .new_from_file(' input.tif ', access= ' sequential ')# pyvipsで画像を読み込む
Image = Image。裁剪(0,0,512,512)#左上から512×512の領域で画像を切り出す
Image = Image .numpy()#图片をメモリ上に展開
cv2.imwrite (out.tif,图片)#画像を書き出し

上のコ,ド,一見問題ないように見えますが,実は致命的なバグがあります。ですが,私はそのバグに気づかずにモデルの学習をし続けてしまい,3日間も時間をロスしてしまいました。

再び百聞は一見に如かず,ということで,上のコードを実際の画像で実行した結果をお見せします。(違いを分かりやすくするため,病理画像ではなく自然画の事例を紹介します)

一目瞭然ですね。画像の色が変わってしまっています。これは,pyvipsとcv2のライブラリ間の仕様の違いを意識せずに処理をつなげてしまったことが原因です。pyvipsは画像を内部的に“RGB”の順で扱うのに対して,cv2は“BGRの順で扱います。つまり5行目のimgage.numpy()コマンドでは,pyvipsが画像を“RGB”順でメモリに格納します。一方,6行目のcv2。imwriteでは,openCVが图像配列を“BGR順の画像と解釈し,画像を書き出します。これが原因で,out.tifの色が変わってしまった,というのがバグの原因です。正しくは,5行目と6行目の間に下の一文を挟む必要があります。

Image = cv2。cv2.COLOR_RGB2BGR cvtColor(图片)# RGBデタをBGRに変換(openCVは画像をBGRデタ順で扱う)

今回の失敗は,入力画像と出力画像の対応をしっかり見れば防げるものです。また,ドキュメントをしっかり読めば各ラ。

そういう意味で,今回のバグは単なる私のケアレスミスなのですが,“MATLABだったら起こりえないミスだったなぁ”という思いが脳裏に浮かんだのも事実。“普段,自分がこんなにもmatlabに守られていたのか”と痛感しました。

Pythonは自由なのがメリットだが,自由すぎるのがデメリット

プライベートでPythonを使うときにも良く感じますが,Pythonは本当に自由度が高い言語です。たくさんのラesc escブラリが公開されており,それらを組み合わせることで様々なことが実現できるからです。先ほどの例ではopenCV, pyVips, Numpyの3つのライブラリを組み合わせて画像処理を行っています。

ただ,自由度が高いということは,メリットばかりではありません。その分プログラマの責任,ケアすべき事柄が増えるからです。各ラesc escブラリをどう組み合わせるのか,そしてその組み合わせは正しく動作するのか。これらを確認する責任がプログラマ側にあります。

今回の私の失敗は,これらの責任を果たさなかった事が原因です。Pyvips, openCVの仕様を(時には英語のドキュメントを読み)調べ,内部でデータがどう保持されているかを理解し,正しくデータが受け渡しできているかを検証する。これが本来,私が果たすべきことでした。

“PyvipsとopenCVを連結すると,RGBとBGRが入れ替わるので注意”。Pythonは,このような警告を発してくれません。そして,rgbとBGRが入れ替わっても,プログラムは正常に動作してしまいます。Pythonを使う上では,私自身が独力でこの警告に気づかなければならないのです。

Pythonのメリットは自由なこと,デメリットは自由すぎること。これが今回私が感じたPythonの特徴です。Pythonは,多彩なラescブラリを自由に組み合わせることができます。ただ,その分ラ。今回お話した私の失敗例を見て,“自力で解決するのは難しそう”と感じた方にとっては,もしかしたらPythonは自由すぎるのかもしれません。一方,関数の仕様書を読み慣れていたり,バグの原因を自力で解決できる方にとっては,Pythonは良い選択肢でしょう。

MATLABは初心者にも快適にプログラムが書ける点がメリットだが,Pythonほどの自由度はない

MATLABは,MathWorks一社という特徴があります。たくさんの工具箱を使うことができますが,それもすべてMathWorks社製です。これが,matlabのメリットだと私は思っています。特に,今回Pythonで失敗を経験した私にとって,このメリットは際立って感じられました。

上記Pythonの画像切り出しスクリプトは,MATLABで書くと以下のようになります。

图片= imread(“input.tif”“PixelRegion”, {[1,512], [1,512]});左上512×512の領域のみを読み込む
imwrite (“out.tif”、图像);切り出した画像を書き出し

まず,matlabだとたった2行で書くことができます。Pythonでは複数のライブラリをまたぐ必要があったため,データの受け渡しにいくつか関数を呼び出す必要がありました。しかし,matlabではその必要はありません。imreadのPixelRegionオプションで部分画像を読み込んで,そのままimwriteで画像を保存できます。さらに,内部デ,タの持,方をプログラマが気にする必要もありません。正しくデ,タの受け渡しが行われるよう,matlabがプログラマを守ってくれるからです。

また,バグが発生した時の対処のしやすさもmatlabのメリットでしょう。ドキュメントはMATLAB公式サイトに全て集約されており,docコマンドで即座に参照できます。どうしても原因が分からないときは,MathWorksの様々なサ,ビスを使うこともできます。テクニカルサポ,トに問い合わせてもいいですし,コンサルティングサ,ビスを利用することもできます。MATLAB的答案に疑問を投稿するのもいいでしょう。Pythonの場合はもう少し解決が複雑になります。先ほど,Pythonで私の失敗例を紹介しましたが,もしあなたの身に同じことが起こったときにどうすればいいか想像してみましょう。自力でバグの原因を探す?適切なコミュニティを探して質問する?方法は色々とあると思います,がいずれにせよ自らの手で解決する必要があります。

もろん,matlabにもデメリットはあります。開発元がMathWorks一社というメリットを挙げましたが,それがそのままデメリットになります。残念ながら,MathWorks一社で開発するMATLAB及び工具箱と,あらゆる組織が開発するPythonでは,単純なライブラリの数に関しては後者に分があるのは認めなければなりません。ただ,MATLAB及びMATLAB工具箱は機能が少ないわけではなく,むしろ機能豊富で,ほとんどのユーザーの要求に応えることができる点も事実です。(多くのプログラマにとっては,Pythonの機能がむしろ豊富すぎるとも言えるかもしれません)

このように,特に初心者にとって快適にプログラムが書けるよう意識されている点が,MATLABの特徴だと私は思っています。仕様を深く理解しなくても高度な関数を使える手軽さ,集約されたドキュメント,手厚いサポ,ト。これらにメリットを感じる方は,matlabがマッチするのではないでしょうか。

おわりに

いかがでしたでしょうか。私のKaggleでの失敗例を通して,MATLABとPythonの違いについて語ってみました。MATLABにはMATLABの,PythonにはPythonのいいところがあります。結局のところ,自分自身のスキルややりたいことに対して,よりマッチしている言語を選ぶことが重要なのだと思います。

|

评论

要发表评论,请点击此处登录到您的MathWorks帐户或创建一个新帐户。