たけのこブログ

凡人が頑張って背伸びするブログ

TellusのGPUサーバからPyTorchの環境を構築する

Tellusとは

宇宙産業を促進するための衛星データプラットフォームとして、Tellusが昨年から始まっています。

Tellus(テルース)は、政府衛星データを利用した新たなビジネスマーケットプレイスを創出することを目的とした、日本初のオープン&フリーな衛星データプラットフォームです。複数のデータをかけ合わせ、新たなビジネス創出を促進するためのあらゆるファンクションを提供します。

本当は始まった当初から解析をゴリゴリやりたかったのですが、当時は研究の実験が物凄く大変で精神的に追い込まれていたので(たった数ヶ月で10キロも増えた)、結局今年の終盤にやる決断ができた次第です。

TellusではTellus OSと呼ばれる操作ツールを用いてJavascriptで衛星画像を切り取って加工してみたり、申請すればjupyterの環境をプラットフォーム内で利用できるので、そこで画像の解析をpythonなどの言語を用いて行うことが可能になっています。

ただ、私の場合ディープなどのそれなりに重い処理を行うことも想定していたので、GPUの高火力コンピューティングの申請をしていました(そして、何週間か待って無事に通りました)。スペックは以下のようになっています。

GPUカード:NVIDIA Tesla V100 for PCI-Express (32GB) ×4
CPU:Xeon E5-2623 v3 4Core×2 (8C/16T 3.0GHz Max3.5GHz)
メモリ:128GB
ディスク(RAID1):SSD 480GB 2台/1組
※お問い合わせ後、個別調整

詳しくは、以下を参考にしてください。環境はUbuntu18.04です。

www.sakura.ad.jp

このスペックがリモートで操作できるのは嬉しいですね。通常なら初期費用で100万は飛んでいきそうな感じです。当初は、申請が通ればこの環境がリモートでタダで使い放題なのかとワクワクが止まりませんでした。

さて、この環境では最初はUbuntuが入っているだけなので、言語環境などのセットアップは自前で行う必要があります。ただ、メールやマイページに記載されていた方法でやるとつまづいたところがあったので、今回は上記の環境からPyTorchのセットアップまでの手順を備忘録として記載したいと思います。

セットアップ手順

ここで行う大まかな手順は以下の通りです。

  • ディープラーニングNVIDIAGPUボードを利用するために以下をインストール
    • CUDA Toolkit
    • GPUボード用ドライバーソフトウェア
    • cuDNNなどのライブラリ
  • anacondaの環境構築
  • PyTorchのインストール

GPUサーバにアクセス

ターミナルを開いて、以下のようにアクセスを行います。申請が通った際の通知メールにログインIDが伝えられるので、それにしたがってssh接続を行います。

$ ssh (メールで送られてきたログインID)@(Tellusのマイページの開発環境利用状況に記載されている環境ホスト名)

パスワードを求められるので、マイページにあるトークン情報を入力すれば接続は完了します。

パッケージのアップデート

# apt update
# apt upgrade

ソフトウェアパッケージのインストール

# apt install build-essential

DKMSのインストール

# apt install dkms

CUDA Toolkitのインストール

次に、搭載されているGPUカードであるNVIDIAを利用するためのToolkitを入手します。ここまではTellusのマイページに記載されている「CUDA Toolkit/GPUカードドライバー導入手順」と同じです。

developer.nvidia.com

しかし、その導入手順に載せてある上の外部ウェブサイトに行くと、CUDA10.2のインストーラーのダウンロード画面に移動してしまいます。PyTorchが現在サポートしているのはCUDA10.1までですし、肝心のTellusの導入手順はCUDA10.0で説明が進んでいます。しかも、なぜかCUDA10.0でインストールができなかったです。こんなエラーが発生しました。

CUDA Installer must be in silent mode to use the toolkit, samples or driver command-line flags. Please also pass -silent to the installer.

ちょっとネットで調べても解決策が出なかったので、PyTorchを入れるのが目的だったのでCUDA10.1を入れることにしました。先ほどの外部ウェブサイトで「Legacy Releases」という項目があり、それをクリックすると過去のリリース版を選べるので、そこにあるCUDA10.1を選択します。その後の選択項目は導入手順の通りで次のようになります。 Operating System: Linux
Architecture: x86_64
Distribution / Version: Ubuntu18.04
Installer Type: runfile [local]

こちらでダウンロードをしたら、SCPなどの手段で高火力GPUサーバーにコピーします。あくまで一例ですが、こんな感じです。

scp -r (ダウンロードしたファイルのパス) (メールで送られてきたログインID)@(マイページに記載されている環境ホスト名):~/

そのあとは、導入手順と全く同じでCUDA Toolkitをインストールします。sudoはつけたと思います。

# chmod +x (ダウンロードしたファイル名)
# ./(ダウンロードしたファイル名) --toolkit --samples --samplespath=/usr/local/cuda-samples --no-opengl-libs

--no-opengl-libsをつける理由としては、OpenGL関連ファイルをインストールすると、X Window Systemベースのデスクトップ環境へのコンソールログインに支障がでることがあるためらしいです。

そして、最後に環境変数を設定するファイルを作成すれば完了です。 /etc/profile.d/cuda.sh

export CUDA_HOME="/usr/local/cuda" 
export PATH="$CUDA_HOME/bin:$PATH" 
export LD_LIBRARY_PATH="/usr/local/lib:$CUDA_HOME/lib64:$LD_LIBRARY_PATH" 
export CPATH="/usr/local/include:$CUDA_HOME/include:$CPATH" 
export INCLUDE_PATH="$CUDA_HOME/include" 

/etc/profile.d/cuda.csh

setenv CUDA_HOME "/usr/local/cuda" 
setenv PATH "$CUDA_HOME/bin:$PATH" 
setenv LD_LIBRARY_PATH "/usr/local/lib:$CUDA_HOME/lib64:$LD_LIBRARY_PATH" 
setenv CPATH "/usr/local/include:$CUDA_HOME/include:$CPATH" 
setenv INCLUDE_PATH "$CUDA_HOME/include" 

やり方はいろいろですが、例えばsudo vi /etc/profile.d/cuda.shとコマンドして、上記の設定をコピペして:wq!で良いでしょう。 最後に設定を反映するため、一同ログアウトしてもう一度サーバーにログインします。

GPUカード用ドライバーのインストール

次に、GPUのカードドライバーをインストールします。これは以下のサイトでダウンロードします。

Download Drivers | NVIDIA

CUDAのToolkitのバージョンだけ10.1なので気をつけて、先ほど載せてあった仕様や導入手順に沿って選んでいけば大丈夫です。

こちらもダウンロードして、ファイルをscpなどの手段でGPUサーバーにコピーすれば大丈夫です。コピーしたら、以下の手順でドライバーをインストールします。

# chmod+x (ダウンロードしたファイル名)
# ./(ダウンロードしたファイル名) --no-opengl-files --no-libglx-indirect --dkms

cuDNNのインストール

最後に、ディープラーニングアルゴリズムを高速化するためのライブラリであるcuDNNをインストールします。

developer.nvidia.com

登録が必要ですが、すぐに終わるのでサクッと登録してダウンロードします。

CUDA10.1のものを選択するといろんなものが出てきますが、「cuDNN Library for Linux」を選択すれば大丈夫です。こちらをクリックしてダウンロードして、先ほどと同じくscpなどで高火力GPUサーバーにコピーします。

# sudo tar -xvzf cudnn-10.1-linux-x64-v7.6.5.32.tar
# sudo mv cuda/include/cudnn.h /usr/local/cuda/include/
# sudo mv cuda/lib64/* /usr/local/cuda/lib64/

これでCUDA関連のインストールは全て終了したので、GPUの状況を確認してみましょう。

$ nvidia-smi

これがうまく起動していればインストールは完了です。

anacondaの環境構築

まず、下記のページに飛んでLinuxを選択してPython3.7 versionのものをDownloadします。

www.anaconda.com

ダウンロードが完了したらscpなどのコマンドでGPUサーバーに転送して、以下のコマンドを実行します。必ず.shファイルが保存されているところで実行するようにしてください。

sudo bash ./Anaconda3-2019.10-Linux-x86_64.sh

無事にインストールが終わると、以下のコマンドが正しく起動すると思いますが

$ conda -V

自分の場合は正しく起動しませんでした。なので、以下のサイトを参考にして、viなどを用いて.bashrcに以下を追加しました。

qiita.com

export PATH=“~/anaconda3/bin:$PATH"

これで先ほどのコマンドが正しく動作しました。

次に、仮想環境を以下のようなコマンドで構築します。pytorchの部分は「環境名」なので、好きな名前で構いません。

conda create -n pytorch Python=3.7 anaconda

そして、アクティベートします。

conda activate pytorch

以下のコマンドで無事に仮想環境が動いているか確認してみてください。

$ conda info -e

ちなみに、その他のコマンドは以下の通りです。

# 非アクティブ
$ conda deactivate
# 仮想環境の削除
$ conda remove -n pytorch --all

PyTorchのインストール

最後に、いよいよPyTorchのインストールをします。以下のURLからコマンドが入手できるので、それをそのままGPUサーバーで打てば大丈夫です。

pytorch.org

conda install pytorch torchvision cudatoolkit=10.1 -c pytorch

最後に、GPUの動作を確認してみましょう。

$ python
>>> import torch
>>> nums = torch.randn(4,4)
>>> nums.cuda() 

最後のnums.cuda()で結果が出てくれれば全ての処理は完了です。

まとめ

今回は、Tellusへ申請すると手に入る高火力GPUサーバーにPyTorchを入れるまでの一連の処理を備忘録として載せました。今後はやってみた解析のコードをこちらで公開しようと考えているので、興味が出た方がそれでTellusに登録するきっかけになってくれれば幸いです。

anacondaの環境構築やPyTorchの導入の際に参考にしたサイト

qiita.com

Simulated Annealing(焼きなまし法)の実装

あくまで研究などとは分野外なので素人ですが、現在は趣味でイジングモデルに基づいた、臨界点で複雑性を最大化するような手法を自作でコーディングしています。その過程で量子アニーリング手法などの原点となっているSimulated annealingを実装するのも悪くないと思い、ウェブサイトなどを参考にして実装した備忘録になります。

Simulated Annealing(焼きなまし法)とは

最適化問題を解くための手法で、ヒューリスティックに解を求めて行くのは良くある基本的な勾配法と同じです。しかし、温度パラメータTを導入していることが大きな特徴になっています。エネルギー変化を-Tで割ったものをexpで括った値である確率p次第では、もしも変更後のコストの値が前に算出したコストより悪かったとしても更新する方策をとります。一見損をしている手法に思えますが、このような手法を取ることによって、更新の際に局所解に陥ることを防いでくれる役割を持っています。 
p=\exp(-\frac{\Delta E}{T})

この手法の重要なパラメータTですが、通常は繰り返し更新すればするほど、減少するように設定されています。これは、最初の段階はコストが悪くても更新する確率pが高いですが、更新するたびに徐々にpの値が小さくなることを意味しています。

実装

実装の際に使用したコスト関数は、以下のサイトに倣ってHimmelblau's functionを使うことにしました。これは、最適化アルゴリズムのパフォーマンスを評価するための関数であり、最小値の位置は分析的に見つけることが可能になっています。

orako-column.com

今回は、上のサイトなどを参考にして3Dに拡張してみました。

import random
import numpy as np
from matplotlib import cm
from mpl_toolkits.mplot3d import axes3d
import matplotlib.pyplot as plt

def cost_function(x, y=0):
    """Himmelblau's function"""
    return ((x**2) + y -11)**2 + (x + (y**2) - 7)**2

INITIAL_STATE = -5 # Initial position
T = 10000 # Temperature
Tmin = 0.0001 # Minimum temperature
STEP = 0.1 # How change variable
COOL = 0.999 # Cooling variable

prev_state = np.array([INITIAL_STATE,INITIAL_STATE])
prev_energy = cost_function(prev_state, 0)
state = np.zeros(2)
while T > Tmin:
    a=0
    #d_state = np.random.randn(2)
    d_state = np.random.beta(1, 1, 2)
    for i in d_state:
        if i > 0.5:
            d_state[a] = STEP
        else:
            d_state[a] = -STEP
        a+=1
    a=0
    state = prev_state + d_state
    energy = cost_function(state) # Calculate cost
    p = np.exp(-np.abs(energy - prev_energy) / T) # Calculate p
    # Update in a case of probability p or smaller energy
    if (energy[0] < prev_energy[0] or random.random() < p[0]):
        if (energy[1] < prev_energy[1] or random.random() < p[1]):
            prev_state = state
            prev_energy = energy
    T = T * COOL


# plot
fig = plt.figure(figsize=(8,8))

ax = fig.add_subplot(111, projection='3d')
x = np.linspace(-5, 5, 100)
y = np.linspace(-5, 5, 100)
X, Y = np.meshgrid(x, y) 
Z = cost_function(X, Y)
plt.title("Himmelblau's function")
plt.xlabel("x")
plt.ylabel("y")
ax.plot_surface(X, Y, Z, cmap=cm.coolwarm, linewidth=0, rstride=1, cstride=1, alpha=.5)
cset = ax.contour(X, Y, Z, zdir='z', offset=-5, cmap=cm.coolwarm)
#cset = ax.contour(X, Y, Z, zdir='x', offset=-5, cmap=cm.coolwarm)
#cset = ax.contour(X, Y, Z, zdir='y', offset=5, cmap=cm.coolwarm)

# Initial end points in 3D space (x,y,z)
mi = (INITIAL_STATE, INITIAL_STATE, cost_function(INITIAL_STATE, INITIAL_STATE))
print(mi)
me = (prev_state[0], prev_state[1], cost_function(prev_state[0], prev_state[1]))
print(me)

#plot points.
res = np.array([mi,me])
print(res)
ax.plot(res[:,0], res[:,1], res[:,2], marker="o", ls="", c=cm.coolwarm(1.))
ax.view_init(azim=-45, elev=15)
plt.show()

結果

f:id:YuKR:20191209090952p:plain

最初の配列が初期位置とコスト関数の値、次の行の配列が終点の位置とコスト関数の値で、それらを合わせた行列が最後の出力結果になっています。 3Dプロットを見ていただくとお分りいただけると思うのですが、終点が最小値の位置に近い値に落ち着いています。STEPやCOOLの値や、何回か試行しても色々値が変わるので、興味がある人は弄ってパフォーマンスを確認して頂ければと思います。

まとめ

今回はSimulated Annealingの実装をちょっとやってみました。イジングモデルを元にした時系列解析手法も作っているので、機会があればそちらも公開できたらと思っています。

日本の修士課程・博士課程の在学中のお賃金事情

追記(2020/09/27)

修士課程や博士課程のお賃金事情でお悩みの方は、良かったらこちらも参考にしてください(特に博士課程に進みたいけど、お金事情が厳しい方はぜひ)。

yukr.hatenablog.com

追記(2021/06/12)

あと、最近では私と同様の方法を試した知人(博士課程)がRA+ベンチャー企業での収入(ソフトウェア開発でリモート)で安定して稼いでるみたいです。試してくれてる人もいるんだなぁと思いました。

追記(2021/06/12)

未だにお賃金事情は解消されてない模様。 引用リツイート見てて思ったのが、この給与形態が当然で特に文系の博士には投資する価値がないと主張してる人達がいることなんですよね。もうちょっと優しく物事言える人っていないんだろうか...汗 K(人間) on Twitter: "センシティブな内容だ……… "

Twitterにて、とある海外大学出身の方から

「日本の修士課程・博士課程の在学中のお賃金事情はどうなのか?」

というような質問をいただいたので、私の認知してる範囲での金銭事情をお話できればと思います。もちろん例外も沢山あるので、ここでの内容はほんの一部に過ぎないかもしれないです。しかし、今月は大学院に進むべきかどうかの相談をされたことが多かったこともあり、私の知ってる範囲だけでも発信することで参考になるのではと思ったので、書き留めたいと思います。ある程度私の主観的な考えも混じっているため、何か間違いがあったりこういう例もあるという方がいましたら、ぜひコメントしてくださると助かります。多分、こういう事情を網羅している記事ってあまりないと思うので、皆さんの知っている情報を記入していただければ幸いです。

修士学生の大学院での主なお賃金

大学院での代表的なバイトとして、TA(Teaching Assistant)やRA(Research Assistant)があります。例外として、独立行政法人関連の研究所(一例としては、○研のJRA制度)で連携大学院として研究されている場合や予算が豊富にある研究室に所属している場合には修士学生でもRAが貰える場合がありますが、大体の修士学生の大学院でのバイトはTAになると思います。 TAは先生が受け持っている授業のコマ数にある程度依存するのでかなりばらつきが大きいと思いますが、相場的に授業一回3000円くらいなので、月々2-3万円くらいだと思います(三つ以上担当すればこれより高額になるかもしれないですが...)。ただ、大学院大学のようなところでは学部生がいないため、授業コマ数が少ない分月々1-2万くらいになるのではないでしょうか。これはあくまでも私や周りの友人に聞いた範囲で平均した額ですが、これに無利子の第一種奨学金(という名の借金)88000円が追加されて、<田舎なら生活できるor都心なら無謀なレベルの生活>という感じになるかなと思います。しかし、これはあくまで生活するだけならという話なので、これに授業料や就活費用などが入ってくると、人によっては一時的な赤字が免れないと思います。

また、全ての学生にTAをさせるのは当然不可能なので、それ以外の学生はバイトをすることになると思います。TA以外のバイトの例は沢山ありますが、私の知りうる限りだと本屋や飲食店のバイト、ベンチャー企業での研修、非常勤の塾講師、プログラミング塾のバイト、NGO活動、短期アルバイトなど様々でした。でも割と塾講師が多かったかもしれないです。中には牧場でアルバイトをしていた方もいました笑

注意点になりますが、TAやRAの就労時間は、特に国公立の大学では予め決められている場合が多いです(週に〇時間以上の就労はダメとか、月に〇時間以上働いちゃダメとか)。以上のことから、修士課程の学生が、TAだけで奨学金を借りなくて良いほど稼ぐのは「複数のTAを組み合わせたとしてもほぼ不可能」です。しかも、多くの大学では年間の授業料より少ない額しか稼げないように設定されているのではないでしょうか。

とはいえ修士課程は二年間だけですし、日本の修士学生(特に理系)はメーカーの推薦枠も豊富にあったりでなんだかんだ待遇が良いですから、博士課程ほど苦しくはない気がします(もちろん研究で苦しむかどうかは別腹です)

博士課程学生の大学院での主なお賃金

これは、先ほど申し上げたTAとRAが収入源になると思います。RAはかなり差があると思いますが、相場的には月々4-10万円のような気がします(例えば理研JRAや一部の研究所のRAはこれより高額のところがありますが...)。そして、RAももちろん就労時間の制限があるものが多いので、こちらも複数のRAをしない限り、国立の年間授業料くらいを超えるとは思いますが、年間で100万を超えるような例はそんなにたくさんない気がします。

ただし、博士課程の学生は学振というものがあるので、こちらに申請して素晴らしい研究と認められれば、月20万円と研究費が手に入ります。20万入れば生活は困らないと思いますが、基本的に副業禁止(ただし、最近では大学のTAやRAは可能になった)なので、年間で240~270万くらいになると思います。学振を通る学生は、申請者のうち20%以下だったと思います。しかし、これに申請するのが全体の博士学生の半分以下と言われているので、博士学生全体で計算したら実際に学振をもらっている学生は、全体の20%よりかなり低い確率になるのではないでしょうか(実際は全体の5%に毛が生えたくらいという報告をTwitterで見た記憶があります)。

最近では、確か朝日新聞で学振の支給額だと都内で生活するのが大変という記事が載っていた気がします。確かに都心の場合は20万なので手取りで14万いくかいかないくらいでしょうから、生活は楽ではないと思います。しかも授業料という負のボーナスが年に二回もありますから、貯金はほとんどできないのではないでしょうか。最近では大学院生の授業料減免で話題になってたりしてますが、これがもしも来年から優秀な学生の授業料も免除にならなかったら、今まで授業料が免除だった方にとってはきつい生活を強いられるかもしれません。私立だと独自の学費免除や給付型もあるので一概に言えないですが...汗

そして、学振に通らなかった学生は、例えば生活していくために民間の給付型助成金などに応募するんですが、これが曲者です。通常は複数の団体に応募すると思うので、いくつも書類を作成しないといけなくなります。助成金には通ったけれども、書類を書くのに必死で半年近く研究の進捗がない同期の知り合いもいました。また、助成金に通ったとしても一部は期限までに実績を作らないといけない場合もあり、自分が今までやってきた研究がおろそかになる例もあったみたいです。これもかなり個人差があると思いますが...。

最後に、助成金も通らなかったor申請しなかったそれ以外の学生は、バイトなどを研究の時間を割いて行う場合が多いと思います。ただ、相当きついと聞きますね...。週に4日以上バイトで働くとなると本当に研究する時間がなくて、それを先生が全く分かってくれなくて毎回脅してくるから死にたいという愚痴をウェブでも現実でもそれなりに聞いたことはあります。本当にここまでくると博士課程の闇としか言いようがないですね。相手側にも情があるのか疑います

まとめと個人的な感想

相談された方からは、海外の大学では学費も免除で保険もある形で入学できると仰っていましたが、残念ながら日本ではそのような待遇は絶滅危惧種だと思います(OISTなどはそれに近い環境かもですが...倍率はお察しですw)。 単一のTAやRAでは間違いなく生活が苦しいので、副業やら助成金やら含めて自分で生活資源を探らなければならない場合が多いと思います。

余談ですが、学振しか安定して生活したりキャリアを築く手段がないような固定観念を持っている方が多い印象が個人的にあります。ウェブで検索しても、「学振を通す書き方のコツor成功エピソード」の記事はたくさんあるのに、「学振なくても稼いで研究生活を送れるコツ」みたいな記事ってどこにもなかったです(少なくとも、私が検索した限りでは見つかりませんでした)。他の可能性を探しても「博士課程が辛い」などのような消極的な情報が混在することも非常に多く、欲しい情報に辿り着けている方が少ないのではないかというのが私の見解です。近年ではフリーランスなどをしながら大学院生活を過ごす学生もチラホラ見かけるので、例えばですが博士課程でもある程度安定してお金を稼いで研究もできるような新しい積極的な情報を発信して増やしていくことで、新しい選択肢を見つけられる可能性が増えていくのかなと思います(全然解決策になってないですが)。

かなりの長文になりましたが、大学院のお賃金事情について私の周りの知人の情報も踏まえて発信してみました。拙い文章ですが、少しでも参考になったら幸いです。 最後に、質問してくださったユーザーさんありがとうございました。

pandasを使いこなせることの重要性

なぜこんなタイトルにしたのか

生産性の高い人間とは、「ある程度完璧でなくてもいいから、素早く結果を出せる人材」だと個人的に思っています。特に、データ解析においては素早く生データを加工できる技術を持つことは非常に重要だと思っています。どんなに最新の機械学習アルゴリズムを試したくても、データが加工できなければsklearnすらまともに動かせません。

もちろん、ある程度のデータ加工はデータベースから抽出する際にSQLなどで対応することは可能なのですが、細かい部分の加工は他の言語で手軽に実行する場合が多いかなと思います(これも個人的な意見ですが...)。

大学の後輩がpythonでデータ解析を行うときに、「何から勉強したら良いかわからない」と言われたことがあります。難しい機械学習アルゴリズムなんて専門的な知識が身についてからじゃないとまともに書くのは大変ですし、結果が出るのが遅いと先生がイライラし始めます(ここから出来が悪いと誤解して大抵発破をかけ始めるか、愚痴を言い出すかの二択だったりゴホンゴホン。もちろん私の身の回りの研究室ではゴホンゴホン)

なので、とにかく何かしらの結果を出せるスキルは大事です。勝手に相手ができると勘違いしてくれることも多いです笑 データの加工に慣れれば、俯瞰的にデータを見たときに関係性を把握しやすくなってきますし、何より手を動かしてるので、自分はちゃんと研究や仕事がやれてると感じられることもあり、あまり精神的なダメージも少ない(はず)。

なので、まずはpandasを使えるようになりましょう。pandasのplot機能はあまり細かい設定もいらないので、初学者は手軽にグラフにもできるので良いと思います。もちろん、seabornも手軽に使えるので、論文の結果にも使えるような描画を出力できると思います。特に最近はjupyterでかけるので、加工した時の様子を逐一見ながら解析を進められるので、試行錯誤しやすいと思います。

オススメの書籍

ここでは、オススメの書籍(というより、学びたての僕が実践した本やよく使う細かい加工)を紹介したいと思います。

まず、こちらの本でpandasとplot機能の章を学べば、大抵のことはできるかなと思います。plot機能の演習では、ハイチでの災害データを元に解析を行なっているので、実戦もできて良いかなと思います。 www.oreilly.co.jp

そのあとは、自分が利用するデータセットを使っていろんな解析を行うのが良いかなと思います。pandasのウェブサイトはたくさんありますが、個人的によく使用するのは「ダミー変数」と「concatなどの結合」、「複数の条件で抽出する」処理と、プロット機能です。もちろん慣れですが、これらの機能が使いこなせるようになれれば、大体のデータ処理に対応できると思います。

まとめ

参考になったかわかりませんが、みなさんのデータの加工が早くできるようになる参考にでもなれれば良いなと思います笑

面倒なのはSeabornに任せるのが一番

久しぶりの更新です。最後に更新して以降、研究やらお仕事が忙しくてそれどころじゃなかった(言い訳)

研究でジャーナルの執筆を始めるとなると、いろんな結果を出さないといけない訳なんですが、ちゃんとしたところに出そうとなるとめちゃくちゃ結果の見せ方を工夫しないといけないんですよね...「研究の内容よりも結果の見せ方でボスに叩かれる」なんて言っていた先輩の愚痴をようやく実感し始めています。

さて、僕は結果は主にMatlabPythonを組み合わせて出しているのですが、Pythonのデータフレームからは.plotで引数を指定してやれば、様々な結果を簡単に弾き出すことができます。ただ、これが条件ごとに(例えば、健常者と患者の群で)出したいとかってなると、条件ごとに抽出して分けたりしないといけなかったりで...。なんだかんだ複雑な結果を出そうとすると、pandasのplot機能は細かい設定がたくさん必要で面倒くさいんですよね汗

そんなわけで、簡単に条件ごとの結果を出したり見せ方を綺麗にできるのがSeabornでした。例えば、カラムに'Condtiion'とかあって、その中にPatientとかControlとかって条件がフラグとして紐づいていたら、hueで指定すれば、同じグラフの中にPatientやControlそれぞれのグラフをプロットしてくれます。colを指定すれば、異なるグラフで描画してくれます。

一番気に入ったのは、相関分析をした時にピアソンの相関係数とp値をグラフ上に載せてくれる機能ですね。統計解析をしなければならない身としては、非常にありがたい機能でした。データフレームさえあれば、例えば

ax = sns.jointplot('time', 'value',data=df,kind='reg').annotate(stats.pearsonr)

で簡単に表示してくれます。まぁ、これは有意差のない相関結果ですが笑

f:id:YuKR:20191114140756p:plain

一応、この結果は切り取っていますが、それぞれ上と右側にデータのヒストグラムも表示してくれているので、データの特性も可視化できていて一石二鳥です。 ただ、Seabornの欠点ももちろんあって、カラーの指定がpaletteなので、 barプロットならいけた気がしますが基本的には色の指定はできません。例えば、同一被験者内の解析をする際に、条件間で行ったタスクは同じ色にして、条件ごとに透明度を変えて分かりやすく表示させるとかが難しいです。これは、pandasのplot機能じゃないと実現できません。 また、Seabornは豊富なプロットの種類がありますが、それぞれオプションが違うので同じオプションだとエラーが起きるとかが結構あります。これも複雑なことができる故の欠点なのかもしれないです。

使っているユーザーとしては、欠点はこのくらいなんですが、それを考慮しても綺麗に作図できるので重宝します。もしも論文でボスに結果の見せ方を突っ込まれて面倒臭いとか、仕事で綺麗な結果を見せたい場合に関しては、ぜひこの機能を使って見てください。一応、自分が主に使用したSeabornのサイトを紹介しておくので、よかったら参考にしてください。

www.mishou.be

qiita.com

PDFMiner使ってPDFをテキストとして抽出

テキストマイニング初心者が調子に乗ってPDFをテキストに変換してみました

ただの備忘録です(思った以上に苦戦したので汗)。仕事などで本格的に自然言語処理をする機会がありそうなので、何となくテキストマイニングをやってみようと思ったのがきっかけです。スクレイピングは取り敢えずガチャガチャやればできそうという根拠のない自信があったので、まずは持ってきたPDFとかをテキストに変換することにしました。調べてみると、PDFMinerというモジュールがあって、こいつがあればなんでもできそうだなと思って初めて見たら...すごく苦戦しました。

参考記事は下記を参照して作ったのですが、もうPDFMinerのバージョンが古いらしく、この通りに動かすと色々エラーが出ます。試行錯誤してなんとか上手く動いたので、バージョンの違いなどによる変更点などは、文末にある参考URLやプログラムのコメント欄を参考にしていただければと思います。ただ、PDFParserの部分だけは以下のようなエラーが出てどうしようもなかったので、スクレイピングして持ってきたPDFを保存して、そのpdfを使ってPDFMinerで処理を行う想定で作りました。

eneprog.blogspot.com

エラー内容

---> 17 parser = PDFParser(fp)
     18 doc = PDFDocument()
     19 parser.set_document(doc)


UnsupportedOperation                      Traceback (most recent call last)
(以下略)
UnsupportedOperation: seek

まぁ...どうせBeautifulSoupとか使うつもりだったので、良いですよね?(震え声) では、以下構築手順になります。

  • まず、pdfminer.sixをインストールします。pdfminer.sixはpython2/3問わず動くらしいので便利みたいです。ちなみに、環境はanaconda3-5.3.0(python3.7)を使用しています。
pip install pdfminer.six
  • 次に、PDFをテキストに変換します。今回は、先ほどの記事を元にエネルギー計画の改定案のpdfを使用します。バージョンの違いなどはコメント文を参考にして頂ければと思います。
# 7月9日に投稿したプログラムは一部誤りがあったので修正
#from pdfminer.pdfparser import PDFParser, PDFDocument(古いっぽいです)
from pdfminer.pdfparser import PDFParser # (from pdfminer.pdfparser import PDFParserみたいです)
from pdfminer.pdfdocument import PDFDocument # (from pdfminer.pdfdocument import PDFDocumentみたいです)
from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter
from pdfminer.converter import TextConverter
from pdfminer.pdfpage import PDFPage

import io

retstr = io.StringIO()

parser = PDFParser(open('energy.pdf','rb'))

try:
    doc = PDFDocument(parser)
except Exception as e:
    print('is not a readable pdf')
parser.set_document(doc)

rsrcmgr = PDFResourceManager()
device = TextConverter(rsrcmgr, retstr)
interpreter = PDFPageInterpreter(rsrcmgr, device)

# doc.get_pages()はバージョンが古くて、PDFPage.create_pages(doc)とするべきみたいです。
for page in PDFPage.create_pages(doc):
#for page in PDFPage.get_pages(doc):
    interpreter.process_page(page)

device.close()

str = retstr.getvalue()

retstr.close()

str

実行結果の一部

' エネルギー基本計画(案) 平成30年5月16日 \x0c 1 目次 はじめに・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・2 第1章 構造的課題と情勢変化、政策の時間軸 第1節 我が国が抱える構造的課題・・・・・・・・・・・・・・・・・・・・・・・・・・4 1.資源の海外依存による脆弱性 2.中長期的な需要構造の変化(人口減少等) 3.資源価格の不安定化(新興国の需要拡大等) 4.世界の温室効果ガス排出量の増大 第2節 エネルギーをめぐる情勢変化・・・・・・・・・・・・・・・・・・・・・・・・・7 1.脱炭素化に向けた技術間競争の始まり 2.技術の変化が増幅する地政学的リスク 3.国家間・企業間の競争の本格化 第3節 2030年エネルギーミックスの実現と2050年シナリオとの関係・・・・・・10 第2章 2030年に向けた基本的な方針と政策対応 第1節 基本的な方針・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・12

ちゃんと出てきました!

あとは、以下の記事を元に正規表現でテキストを整形すると綺麗に出てきました。

eneprog.blogspot.com

以下、プログラムと結果になります。

import re
str2=re.split("\x0c 2\s+",str) 
str2=str2[1]
str3=re.sub(r"\x0c(\s\d+|\d+)\s+","",str2)
str3
str4=re.split("\x0c",str3) 
str4=str4[0]
str5=re.sub("\s","\n",str4)
str6=re.sub(r"([a-zA-Z])\n",r"\1 ",str5)
print(str6)
str7=re.sub(r"([①-⑳])\n",r"\1",str6)
str8=re.sub(".\n",".",str7)
f = open('enegy.txt','w')
f.write(str8)
 
f.close()

整形した結果の一部

はじめに
2011年3月の東日本大震災及び東京電力福島第一原子力発電所事故を受けて、政府は、2014年4月、2030年を念頭に、第4次エネルギー基本計画を策定し、原発依存度の低減、化石資源依存度の低減、再生可能エネルギーの拡大を打ち出した。
第4次エネルギー基本計画の策定から4年、2030年の計画の見直しのみならず、2050年を見据えたパリ協定への対応、より長期には化石資源枯渇に備えた超長期の対応、変化するエネルギー情勢への対応など、今一度、我が国がそのエネルギー選択を構想すべき時期に来ている。このため、今回のエネルギー基本計画の見直しは、2030年の長期エネルギー需給見通し(2015年7月経済産業省決定。以下「エネルギーミックス」という。)の実現と2050年を見据えたシナリオの設計で構成することとした。

どうやら、綺麗に整形できていそうです。あとは、janome,MeCabなどで色々解析ができそうです。

まとめ

今回は、PDFMinerを使ってPDFをテキストにしました。これ以降は、どっかの企業や省庁の公開してるPDFファイルを持ってきて、PDFMinerやってからjanomeとgensim組みわせて解析したり...かな?(余裕があればそのうち)

バージョンの違いなどに関する参考資料(一部)

stackoverflow.com

pythonのバージョン更新したらstatsmodelsで分散分析できなくなった件

分散分析ができなくなっちゃった...汗

前回の記事からanacondaのバージョンを上げました。

yukr.hatenablog.com

anaconda3-4.3.0からanaconda3-5.3.0バージョンを更新して、今日は実験の解析でstatmodelsを使って分散分析をしようとしたら、以下のようなエラーが...

---------------------------------------------------------------------------
AssertionError                            Traceback (most recent call last)
<ipython-input-6-0d5566028b0b> in <module>()
     10 # Make a model
     11 formula = 'percentage' + '~Cond'
---> 12 lm = ols(formula, data = df_group1).fit()
     13 result = sm.stats.anova_lm(lm)
     14 print(result)

あれ、今までできていた統計解析ができない(笑)。 調べたところ、statsmodelsでformulaのparserに使用されるpatsyと呼ばれるライブラリにバグがあったことが原因らしいです。これは、stackoverflowやstatmodelsのissuesにも対策方法が書かれていました。

stackoverflow.com

github.com

Python 3.7.1から発生しているバグみたいですね。肝心の解決方法は案外シンプルでpip install -U patsyでpatsyのバージョンを更新すれば問題ないです。バージョンを更新する前は

In [1]: import patsy

In [2]: patsy.__version__
Out[2]: '0.5.0'

となっていますが、更新すれば0.5.1にバージョンアップされると思います。結果、無事に分散分析できました。0.05<0.07なので、有意傾向みたいです笑

# Make a model
formula = 'percentage' + '~Cond'
lm = ols(formula, data = df_group1).fit()
result = sm.stats.anova_lm(lm)
print(result)
            df        sum_sq        mean_sq         F    PR(>F)
Cond       1.0  2.215560e+05  221556.004523  3.505502  0.075861
Residual  20.0  1.264047e+06   63202.360938       NaN       NaN

分散分析がしたい場合は以下のような記事を参考にすると良いと思います。機会があれば、分散分析や多重比較補正の方法などを本格的に載せようかなと思います。今日はとりあえずここまで。

www.monotalk.xyz