Lapack for Torch
ちょっとSVDが必要だったのでtorch.svdをしたら"LAPACKがないよ"と怒られました。
torchの線形代数ライブラリはLapackをラッパしているだけなので、そもそもコンパイル時にLapackがないとだめ。
ということでOpenBLASをインストールする。
git clone https://github.com/xianyi/OpenBLAS.git
cd OpenBLAS
make NO_AFFINITY=1 USE_OPENMP=1
sudo make install
これで/opt/OpenBLASにBLASが入ります。
あとはpathを通す。
export CMAKE_LIBRARY_PATH=/opt/OpenBLAS/include:/opt/OpenBLAS/lib:$CMAKE_LIBRARY_PATH
このパスが正しく通っていればTorchの再コンパイルでLapackが使えるようになっているはず。
Installing CUDA9 + CuDNN7 + Torch on CentOS 7 (Japanese post + English post)
このポストの目的
下記の自著記事を基にして、CUDA8 + CuDNN5.1はinstallした計算機があります。
今度はこのマシンのCUDA, CuDNNを更新します。
Purpose of this post:
update the CUDA (8 --> 9) and CuDNN (5 -->7) on CentOS 7.
作業開始!
CUDA, CuDNNのダウンロード
まずはnvidiaの公式ページよりCUDAのrpm(network install)とCuDNNのtgzを確保します。
Download the .rpm file of CUDA9 (network install) and .tgz file of CuDNN7.
CUDA Toolkit Download | NVIDIA Developer
NVIDIA cuDNN | NVIDIA Developer
CUDA、CuDNNのインストール
特に何も考えずにrpmインストールです。
Simplu install CUDA from RPM.
sudo rpm --install cuda-repo-rhel7-9.0.176-1.x86_64.rpm
sudo yum clean expire-cache
sudo yum install cuda
環境変数をアップデートします。sourceを忘れずに。
Update the environmental variables. Do not forget source-ing!
export PATH="/usr/local/cuda-9.0/bin:$PATH"
# THIS IS OBSOLETE export PATH="/usr/local/cuda-8.0/bin:$PATH"
export LD_LIBRARY_PATH="/usr/local/cuda-9.0/lib64:$LD_LIBRARY_PATH"# THIS IS OBSOLETE export LD_LIBRARY_PATH="/usr/local/cuda-8.0/lib64:$LD_LIBRARY_PATH"
CuDNNについては、.tgzファイルを解凍して、出来上がるcudaディレクトリの中身を/usr/local/cudaディレクトリにコピーするだけです。
Copy the contents of the CuDNN .tgz file to /usr/local/cuda.
sudo cp -a cuda/lib64/* /usr/local/cuda/lib64
sudo cp -a cuda/include/cudnn.h /usr/local/cuda/include
TorchのRe-install
事前情報を得ていたので、以下の環境変数を設定。
Set the following varaible.
export TORCH_NVCC_FLAGS="-D__CUDA_NO_HALF_OPERATORS__"
Torchディレクトリからinstall. 躓いたら、./clean.shをしてからもう一度やってみましょう。
Install. If you failed, try ./clean.sh, then update all relevant packages and libraries.
cd ~/torch
./install-deps
./update.sh
./clean.sh
export TORCH_NVCC_FLAGS="-D__CUDA_NO_HALF_OPERATORS__"
./install.sh
<<After successful installation, do luarocks for torch packages>>
OpenNMT-py "raise lengths array has to be sorted in decreasing order"
まだクローズしていないバグを踏んでちょっと時間をとられたので情報共有です*1
OpenNMT-py, 正確にはtorchtext-0.20の修正のせいで、いま、最新のOpenNMT-pyをgitダウンロードで使うと、train.pyやtranslate.pyが表題エラーの通りに死ぬ事象が起きています。
フィックスの方法としては、torchtextのバージョンを下げるのが一番簡単なのですが、今後pytorch, openNMTはtorchtext-0.20の方針でいくので、このworkaroundはあまりアレです。
10/30追記
下記の修正で訓練(train.py)は動くのですが、どうやらtranslate.py(翻訳側)はだめなようです。なので、現段階はtorchtext-0.1.1にダウングレードしてください・・・
で、私の修正方法ですが、
- torchtextをpythonシステムからアンインストール
- pipで改めて最新版のtorchtextをインストール
- 上記リンクの中ほど、@JianyuZhan さんがベタ書きしているパッチの内容を OpenNMT-py/onmt/IO.py, OpenNMT-py/train.py, OpenNMT-py/translate.pyにそれぞれ適用する
の3段階でした。
*1:NMTやっていて、しかもpytorchという奇特な方にしか役立ちませんが・・・
slack webhookでログをslackに自動投げ込み
webhookなる仕組みを使って、slackにcurlで直接メッセージを投げ込むことができるらしい。これ使えば、入力フォームから誤訳文対が報告されるたびにslackに投げてみることができるっぽい?
とりあえずslackの公式APIページを見ると使い方が一番わかりやすい。
curlでPOSTするために、メッセージ取ってきて、JSON形式にしてあげればよろしい。
あとはメッセージを取得する方法(最新のログファイルを監視して追いかける)と、それをJSONにフォーマットする部分ですね。
ログ監視パート
ログ監視、tailfとgrepで頑張るのも良いですが、logmonっていうのもあるみたい。
service コマンドで動かせるっていうのはわかりやすくていいですね。
我々の例だと、
/var/www/html/log.txt に全部書き出されるはずなので、これを監視して、何か入ってきたらechoなりで標準出力に吐き出されるようにすればいいのかな?
(logmonをインストールしてから) /etc/logmon/logmon.conf
# Monitor for messages
:/var/www/html/log.txt
(,) # commaは絶対あるので
echo -n "<%%%%>" >> /var/log/logmon-enja.log
# sudo service logmon check
# sudo service logmon restart
よし。
slack webhookパート
これとは別にslack webhookをやる。
送るものとかを整形することを考えると、何らかのstdin入力を受け取って、
各行ごとに処理、jsonに整形、curlでPOST、というスクリプトを書くのがいいかなぁ。
このあたりにしたがって順番にやってみる。
単純POST by curl
slackのアプリのあちこちをいじるとincoming webhookを設定するところにいくので、送りたいchannelを指定してwebhook urlを取得する。
これをcurlでPOSTする。curlの例文はwebhook URLを取得したら下に書いてあります。優しさ。
curl -X POST --data-urlencode 'payload={"channel": "送るチャンネル名", "username": "goyakubot", "text": "This is a webhook test", "icon_eomji": ":ghost:"}' https://hooks.slack.com/services/XXXXXXXXXXXX
おお、とどいた!これだけでうれしい!
スクリプト経由にする
慣れたpythonにstdinでファイルとかcatして、見た目お化粧したい。
jsonとrequestsモジュールを使えば簡単簡単。
python3でも日本語処理が必要になるのね。。。
(slack_webhook_post.py)
# -*- coding: utf-8 -*-
#
# given the stdin INPUT (tab-separted), break in line, send.
import json
import requests
def _main():
# Set the webhook_url to the one provided by Slack when you create the webhook at https://my.slack.com/services/new/incoming-webhook/
webhook_url = "https://hooks.slack.com/services/XXXXXXXXXXXXXXXXXXXXXXXX"
slack_data = {
"channel": "送るチャンネル名",
"username": "goyakubot",
"text": "This is a webhook test from パイソンだよ",
"icon_eomji": ":ghost:"
}
response = requests.post(
webhook_url, data=json.dumps(slack_data, ensure_ascii=False).encode("utf-8"),
headers={'Content-Type': 'application/json'}
)
if response.status_code != 200:
raise ValueError(
'Request to slack returned an error %s, the response is:\n%s'
% (response.status_code, response.text)
)
# end main
_main()
やったぜ。
あとはtext部分を通常のpythonと同様にinput()から受け取った内容でparseすればよいね!
結合パート
logmon.confのecho部分を、メッセージゲット --> Pythonにパイプ、これでいいはず
echo -n "<%%%%>" >> /var/log/logmon-enja.log
--->
echo -n "<%%%%>" | /full/path/to/python /full/path/to/slack_webhook_post.py
できたー!!
とおもったらechoからのメッセージに日本語が入るとだめ。なぜ・・・
に回答がありました。つまり、locale環境変数が効かないということです。
echo -n "<%%%%>" | /full/path/to/python /full/path/to/slack_webhook_post.py
-->
echo -n "<%%%%>" | PYTHONIOENCODING=utf-8:surrogateescape /full/path/to/python /full/path/to/slack_webhook_post.py
で解決!!
Webサーバー構築(Apache+PHP) の練習
ちょっとお仕事で
*既定の入力フォーマットでいろいろな人から入力を集めて
*入力結果を保存して
*AWS S3やslack botに入力結果の保存内容を投げる
ということがしたくなったので、webサーバを構築してみる
AWSインスタンス
まずサーバとなるインスタンスを立てる。
*IPv4パブリックIPを与えること
*セキュリティグループで会社内ネットワークのIPからHTTPアクセスを許可する
だけ忘れずに設定する。後者は後でも追加可能。
仮にパブリックIPが12.345.6.78だとする
Apache
まず基本であろうApache(httpd)でウェブサーバサービスを立てる
sudo service httpd start
これでひとまずAWSインスタンス上でhttpdサービスがスタートした。
これだけで、会社内ネットワーク上のマシンから、ブラウザで
12.345.6.78
と入力すると、apache server testページが出てくる。やったね!
特別portの指定
/etc/httpd/conf/httpd.conf内のListen項目に
Listen 8080
を追加してからhttpdをrestartすると、
12.345.6.78:8080
でも行けるようになるね。使うライブラリとか、排他的な制御とかそういうときにport番号指定したりするときはこうする?
自前html!
httpd.confを見ると
DocumentRoot "/var/www/html"
となっています。ので、http://12.345.6.78はこのパスを実際には見ることになります。
日本語コーデックの確認も兼ねて、
を参考にさせていただいて、簡単htmlを置きましょう。
sudo emacs /var/www/html/sample.html
[sample.html]
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta http-equiv="Content-Type" content="text/html; charset=euc-jp">
<title>テスト</title>
</head>
<body>
テスト
</body>
</html>
これで
12.345.6.78:8080/sample.html
にアクセスします。
「テスト」とだけ表示されるページができたら成功ですね!
入力フォームつくるー
まずはテキストボックスしかないページを作るぞー
5.1 HTMLフォームを使ったデータの入力とWebサーバ側での受信
こういうページを参考にしますよー
今回の目標
翻訳の失敗例を集めたい!ので
*ユーザさんに「翻訳クエリ」と「失敗した翻訳結果」を入力してもらう
*ボタンを押すと2つがまとめて保存なり送信される
という機能がほしいですね。
ページの要素として
*テキストボックスが2つ
*送信するボタン
の2つが必要です。これはhtml内の<form>タグを作って、その中に
テキストボックス2つとボタン1つを配置して完了します。
<form action="collection.php" method="POST" enctype="multipart/form-data">
<table>
<tr>
<td>
<textarea name="input" rows="3" cols="100" placeholder="翻訳に失敗した入力文章をここに入れてください(500文字以内)。" maxlength="500"\
class="form-control"></textarea>
</td>
<td>
<textarea name="output" rows="3" cols="100" placeholder="失敗した翻訳結果をここに入力してください(500文字以内)。" maxlength="500" cl\
ass="form-control"></textarea>
</td>
</tr>
</table><p>
<button type="submit" class="btn btn-primary btn-lg"> 報告するマン!! </button>
</p>
</form>
アクション機能として
*ボタンを押すと2つのテキストボックスの内容を取得する
*確認用に受け取った2つの内容を表示する
が必要です。
機能部分はPHPで書くのが簡単っぽい?ので、phpのファイルを作成して処理させます。
まずPHPを動かすようにします(これに気づかず2時間溶けた)
を追加。
で、collection.phpをhtmlと同じ場所において、
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>sample</title>
</head>
<body>
<table border="1">
<p>
<p>
<tr>
<td>翻訳クエリ</td><td><?php echo htmlspecialchars($_POST["query"], ENT_QUOTES); ?></td>
</tr>
<tr>
<td>誤訳結果</td><td><?php echo htmlspecialchars($_POST["translated"] , ENT_QUOTES); ?></td>
</tr>
</table>
</body>
</html>
これで、報告すると報告結果がブラウザにでるようになります.
入力された内容を保存したいー
これでpostでデータの受け渡しはできるようになったけども、このままだと送信のたびにページが切り替わってしまう。
そこで*送信結果の表示の裏で、ファイルに送信結果を書きだす
これができるようになりたい。
これで行けた。
【PHP】フォームから送信された情報をファイルに保存する方法
# collection.php
# 上記の</table>と</body>の間に以下を挿入します
<!-- sent to the file-->
<?php
if ( isset($_POST["query"]) && ($_POST["query"] != "") ) {$query = $_POST["query"];
if( get_magic_quotes_gpc() ) { $query = stripslashes("$query"); } // Escaping quotes
$query = htmlspecialchars ($query); // prohibit HTML tags
print "query=$query \n ";
if ( isset($_POST["translated"]) ) {
$translated = $_POST["translated"];
if( get_magic_quotes_gpc() ) { $translated = stripslashes("$translated"); } // Escaping quotes
$translated = htmlspecialchars ($translated); // prohibit HTML tags
print "translated=$translated \n ";
}
$time = date("Y/n/j G:i"); //日時の取得
$write = $time . ", " . $query . ",". $translated . "/";
$log = fopen ("log.txt","a"); // open with write mode
flock ($log, LOCK_EX); // lock the output file
fputs ($log,$write); // file write
flock ($log, LOCK_UN); // unlock the output file
fclose ($log); // close
}
?>
<p>
<h3>Above content is sent to the file. thanks.</h3>
<p>
これで、/var/www/html/log.txtに書き込まれるはずです。
・・・できませんでした
SE linux!!
/var/www/htmlは通常rootのものなので、apacheさんなどには書き込めません。
そこで
Apache - Apacheのドキュメントルートのパーミッションと所有権に関して(2111)|teratail
などを参考にしてパーミッションを変えます。
groupadd apache
usermod -a -G apache apache
usermod -a -G apache centos
chown root:apache /var/www/html/
chmod 2775 /var/www/html/ -R
これでも書けないので、SE Linuxを疑います。
ApacheでSELinuxが原因で403 Forbiddenエラー - カタカタブログ
sudo setenforce 0 # SElinux一時停止
これで・・・書き込める!やっぱSE linuxのせいだった!
画面切り替えたくない!
ひとまず入力フォームの入力内容を書きだせるようになったけど、
今は送信のたびに画面が変わるのでたくさん書いてもらうには面倒。
そこで、
*送信してもページが切り替わらないで、「送信したよ!」とだけ表示が増える
*つづけて送信できる
としたい。
簡単には、sample.phpの中で直接php処理を全部書いてしまえばよい。
具体的にはsample.phpの中の次の文を書き換えて・・・
<form action="collection.php" method="POST" enctype="multipart/form-data">
-->
<form action="sample.php" method="POST" enctype="multipart/form-data">
にして、collection.phpの中の実際にphp処理する部分をそのままsample.phpの中に書けばOK.
AWSやSlackへの投稿は次の記事に続く(かもしれない)