kuroの覚え書き

96の個人的覚え書き

文字列とQRコードを並べて合体した画像を作成する。

テプラには文字列からQRコードを生成して、テープに印字する機能があるのだが、このQRコード生成と文字情報の印字の入力は別系統な操作が必要で結構面倒臭い。
なので、QRコードと文字情報をまとめて画像にしてしまって画像挿入機能一操作だけで完結できるようにすると良いのではないかな。
ということでQR生成と合わせて文字も画像化してこれらを合体してやりたい。
QR生成と文字の画像化まではできているのであとは合体だな。

これにはpillowモジュールが使えるようだ。
要するに新規画像を作成して、その画像の適当な座標にパーツとなる画像をprintするという手順のようだ。
つなげ合わせる画像のサイズにぴったりの余白のない合成画像を作りたければ、それぞれの画像のサイズを調べてそれらを足し算した新規画像を用意すると良いというわけ。

    from PIL import ImageFont
    from PIL import Image
    from PIL import ImageDraw

    fontFile = 'ipaexg.ttf'
    font = ImageFont.truetype(fontFile, 64, encoding='utf-8')

    p_id2 = 'ID: ' + p_id
    w, h = font.getsize(p_id2)
    print('%s w:%d h:%d' % (p_id2, w, h))
    im = Image.new('RGB', (w, h), (255,255,255))
    draw = ImageDraw.Draw(im)
    draw.text((0, 0), p_id2, fill=(0,0,0), font=font)
    data = dir + '/id_' + p_id + '_id.png'
    im.save(data)

    plant_id = 'Plant: ' + plant_id
    w, h = font.getsize(plant_id)
    print('%s w:%d h:%d' % (plant_id, w, h))
    im = Image.new('RGB', (w, h), (255,255,255))
    draw = ImageDraw.Draw(im)
    draw.text((0, 0), plant_id, fill=(0,0,0), font=font)
    data = dir + '/id_' + p_id + '_pid.png'
    im.save(data)

    p_date ='Date: ' + p_date
    w, h = font.getsize(p_date)
    print('%s w:%d h:%d' % (p_date, w, h))
    im = Image.new('RGB', (w, h), (255,255,255))
    draw = ImageDraw.Draw(im)
    draw.text((0, 0), p_date, fill=(0,0,0), font=font)
    data = dir + '/id_' + p_id + '_pdt.png'
    im.save(data)

    owner = 'Owner: ' + owner
    w, h = font.getsize(owner)
    print('%s w:%d h:%d' % (owner, w, h))
    im = Image.new('RGB', (w, h), (255,255,255))
    draw = ImageDraw.Draw(im)
    draw.text((0, 0), owner, fill=(0,0,0), font=font)
    data = dir + '/id_' + p_id + '_own.png'
    im.save(data)

ここまでで4つの文字データを画像データに変換している。

    im0 = Image.open(dir + '/id_' + p_id + '_id.png')
    im1 = Image.open(dir + '/id_' + p_id + '_pid.png')
    im2 = Image.open(dir + '/id_' + p_id + '_pdt.png')
    im3 = Image.open(dir + '/id_' + p_id + '_own.png')
    w0, h0 = im0.size
    w1, h1 = im1.size
    w2, h2 = im2.size
    w3, h3 = im3.size

ここで書く画像のサイズを調べている

    w = max(w0, w1, w2, w3)

こうやって一番大きい画像に合わせて画像を作成すれば無駄が出ないはずなんだけど、なぜかエラーが出てうまくいかない・・・
maxに必要なモジュールってなんかいるのかな?
仕方がないので、とりあえず横幅は十分なサイズで一律固定として処理する。

    w = 800
    h = h0+h1+h2+h3
    im = Image.new('RGB', (w, h), (255,255,255))
    im.paste(im0, (0, 0))
    im.paste(im1, (0, h0))
    im.paste(im2, (0, h0 + h1))
    im.paste(im3, (0, h0 + h1 + h2))
    data = dir + '/id_' + p_id + '_merge.png'
    im.save(data)

    im1 = Image.open(dir + '/id_' + p_id + '.png')
    im2 = Image.open(dir + '/id_' + p_id + '_merge.png')
    w1, h1 = im1.size
    w2, h2 = im2.size

    im = Image.new('RGB', (w1 + w2, h1), (255,255,255))
    im.paste(im1, (0, 0))
    im.paste(im2, (w1, 30))
    data = dir + '/id_tag.png'
    im.save(data)

こんな感じに座標を指定して貼り付けてやればいいのだね。


ちなみに12mm幅のテープに印刷したらQRのドットが抜けてしまうのか読み取れず18mmのテープが必要であった。
テプラのソフトで生成した QRコードだと読めたんだけどな。まあ4段に組んだ文字列は12mmじゃ虫眼鏡で見ないと読めないから18mmでいいんだけど。

QRコードをpythonで作る(その2)

QRコード生成をFlaskのwebアプリから行ってみる。
2つのパターンを想定。
前もってデータベースのIDごとのQRコードを生成。
データベースの1エントリーからQRコードを生成。

from functools import wraps
from flask import request, redirect, url_for, render_template, session
from flask_wtf import FlaskForm
from werkzeug import secure_filename
from wtforms import StringField, IntegerField, SubmitField, BooleanField
from ..models import Test
from testDB import Session
import os, shutil,, qrcode

class qrForm(FlaskForm):
    id = StringField('ID')
    qr1 = IntegerField('min')
    qr2 = IntegerField('max')
    submit = SubmitField('Submit')

@app.route('/qr/', methods=['GET', 'POST'])
def qr_index():
    form = qrForm()
    p_id = request.args.get('id', type = str)
    session = Session()
    q = session.query(Test)

# qr1~qr2の連番でQRコードをまとめて生成する。
    if form.qr1.data:
        dir = "./qr"
        if os.path.exists(dir):
            shutil.rmtree(dir)
        if not os.path.exists(dir):
            os.makedirs(dir)
        min = form.qr1.data
        max = form.qr2.data + 1
        for qr in range(min, max):
            qr = str(qr)
            img = qrcode.make('http://k-kuro.hatenadiary.jp/test_edit/?id=' + qr)
            data = dir + "/id_" + qr + '.png'
            img.save(data)
        flash('QR codes generated')


#データベースから1エントリーを選んでQRコードを生成。
    if p_id:
        # q = q.filter(Test.id==p_id).one()
        # plant_id = q[2]
        # date = q[4]
        # owner = q[8]   #この辺はまだ実装していない
        dir = "./qr"
        if os.path.exists(dir):
            shutil.rmtree(dir)
        if not os.path.exists(dir):
            os.makedirs(dir)
        img = qrcode.make('http://k-kuro.hatenadiary.jp/test_edit/?id=' + p_id)
        data = dir + "/id_" + p_id + '.png'
        img.save(data)
        flash('QR code generated')
    return render_template('qr.html', form=form, contents=q)

だいたいこんな感じで./qrディレクトリに画像が作られることを確認。
これをダウンロードする仕組みとテプラなり、タックシールなりに印刷する手段を考えないと。

#今回のアドレスは架空。

for loopの中でintとstrを連結しようとしてハマったのはお約束。
やっぱりちゃんとローカルでテストしながらやらないと遠回りになるな

次は文字を画像化してQRコードと連結してテプラで印刷しやすいように加工だ。
f:id:k-kuro:20190501194050p:plain
こんな感じ

Pillow(PIL)で文字列を画像として保存(位置・サイズ自動調整) - cloverrose's blog
指定のフォントファイルを使って描画した文字列を画像ファイルに保存 - 強火で進め
Python, Pillowで画像を縦・横に連結(結合) | note.nkmk.me
この辺を参考に

fontとしてIPAフォントを使ってみる
IPAexフォント/IPAフォント | IPAフォントのダウンロードサイトです

import sys
from PIL import ImageFont
from PIL import Image
from PIL import ImageDraw

fontFile = 'ipaexg.ttf'
font = ImageFont.truetype(fontFile, 64, encoding='utf-8')

text = u'謹賀新年'
w, h = font.getsize(text)

print('%s w:%d h:%d' % (text, w, h))

im = Image.new('RGB', (w, h), (255,255,255))
draw = ImageDraw.Draw(im)
draw.text((0, 0), text, fill=(0,0,0), font=font)

im.show() 
im.save('image.png')

載っていたコードをちょいといじってpython3で実行してみた。
f:id:k-kuro:20190501220442p:plain
なぜ謹賀新年w
あ、今日から令和。おめでとう。

QRコードをpythonで作る

ラボの物品や実験植物の管理をやりたい。
サーバにデータを置いておいて、WEBアプリで管理できるようにし、物品をQRコードで紐づけておく。物品にそのQRコードを貼り付けておいて、スマホカメラで見ると、WEBに飛んでその場でデータを編集、statusを変更などできるようにする。

まあSQLベースのwebアプリはもうチョチョイと作成できたので、あとはQRコードだな。

Pythonの「qrcode」を使ってQRコードを生成する - Qiita

このページを参考にするならpythonに pillowと qrcodeというmoduleを入れておいて

>>> import qrcode
>>> img = qrcode.make('http://k-kuro.hatenadiary.jp/entry/20190423/1556028585')
>>> img.save('test1.png')

これだけでQRコードは生成完了。
webで表示させると
f:id:k-kuro:20190428222250p:plain

こんな感じに確かにできている。(このQRはこのサイトの一つ前のエントリー)

これをラベルシートに印刷して物品に貼り付けておけば、スマホで管理できるわけだ。

プロジェクト進捗管理とコミュニケーションツールの構築

現在ラボメンバー間の情報共有にはSlack、Benchiling、Google calendarとバラバラのツールを使っている。
そこにプロジェクト進捗管理グループウェアを追加しようということになったので、RedMineをサーバに立ち上げてみた。
だが、うちのサーバはファイアウォール内のサーバなので、外からアクセスできなくて不便。
ということで次に、外にレンタルしているサーバValue-serverにRedMineを入れようと頑張ってみたものの、rootが使えないとやはり構築に苦労した。
第一RedMineはITバリバリじゃないメンバーには敷居が高すぎて、試験運用してもさっぱり使ってもらえなかったという反省もあって、低機能だけどとっつきやすい、まあ、ToDoメモに毛の生えたくらいのツールを自前で用意するか、ということになった。
Value-serverで標準で使えるようになっているWEBツールはWordPressMovableTypeXOOPSの3つ。
とりあえずこれまでに使用経験のあるXOOPSでサイト構築を始めてみたのだが、XOOPSってすっかりオワコンなのか、情報も更新も止まって久しい感じで全然うまく構築できない。
MovableTypeも一瞬かじったことがあるといえばあるが、結局、現在WordPressの一人勝ちじゃなかろうか、ということでWordPressを初めてまともに触ることになった。
Value-serverで簡単にインストールできるようになっているので、特に問題なくインストールは完了。
テーマはシンプルなのが良かろうということでDanというものを使ってみる。
メインの進捗管理はCollabPressというプラグインを使うことにし、登録メンバーのみアクセスできるサイトとすべく、WP Maintenance Modeというプラグインを入れる。
f:id:k-kuro:20190423225129p:plain
権限を設定し
f:id:k-kuro:20190423225227p:plain
アクセスを制限していることを示す入り口を設定

またCollabPressは
f:id:k-kuro:20190423225321p:plain
こんなふうに制限をかけておく

登録するユーザーは
f:id:k-kuro:20190423225436p:plain
寄稿者レベルにしておく

さて、これでプロジェクト管理はそれなりにできるようになったので、もう一点。Slackは無料プランでやっているがデータをやり取りしているとあっという間に容量制限に達してしまい、投稿できないということが起こっていたので、どうにかしたいと思っていた。そこで、WPのブログ、及びコメントを利用して、データのやり取りができるようにしてやることにした。ただし、WPではSlackのような携帯アプリとかないので投稿があったときに通知を受けることができないのは問題だ。そこでWPに書き込み、データアップロードしたら、その旨Slackに通知を飛ばすプラグイン、その名もSlackをインストールした。
f:id:k-kuro:20190423230104p:plain
このプラグインはSlackのWEB APIを利用して通知を送るようになっている。

f:id:k-kuro:20190423230351p:plain
incoming-webhookというのをSlackの設定からひらき、接続したいチャンネルを選択して
f:id:k-kuro:20190423230610p:plain
インテグレーションの追加をポチッと。

WPのダッシュボードにできたSlack というタブで
f:id:k-kuro:20190423230914p:plain
こんな感じに設定して出来上がり。

キーボードレイアウトの設定

サーバにはCentOS7をインストールして使っている。
基本的にサーバにはsshvncで接続して使っているわけだが、端末としてはMacOSXを使用しており、キーボードもmacの(それもかなりレガシーな)US配列のものを使っているため、いまいちキーマップが一致せず、意図した動作ができないということが多かったので、その辺の環境を一度整理してみることにした。あとあまり必要ではないのだけれど日本語の入力、表示も一応できるようにしたい。

初期状況:
CentOS7はlocaleを日本語としている。
super keyが割り当てられていない?
日本語入力ができない。
Macで作成した日本語ファイルが文字化けする。日本語をmacからCentOSにコピペすると化ける。

まず行ったこと:日本語入力環境を入れる。
アプリケーション→システムツール→設定
を開く
地域と言語を選択すると
f:id:k-kuro:20190421191828p:plain
こんな感じになっている。入力ソースに日本語、とあるから日本語が入力できるのかと思ったら、どうやらできない。
したのプラスボタンを押して
f:id:k-kuro:20190421192005p:plainf:id:k-kuro:20190421192028p:plain
日本語(かな漢字)を追加してやると入力、漢字変換もできるようになるというわけ。
f:id:k-kuro:20190421192148p:plain
変換のショートカットなどを変更するならここをいろいろいじる。

で、普通に半角英数入力とちゃっちゃと切り替えて使うには
f:id:k-kuro:20190421192315p:plain
この英語(US)も足しておく必要がある。(特にmacのUSキーボードで入力しているなら以下の理由によりマストだと思う)

さて、これで漢字変換できるようになったが、英数・かな漢字の切り替えのショートカットがこのままでは使えない(VNC環境で)
というのもMacのUSキーボードにはかな・漢字キーなどがないからね。
入力ソースのオプションというボタンを押すと
f:id:k-kuro:20190421192850p:plain
こんな風に書かれていて、変更を受け付けない状態になっているのだが、このsuperキーってのがMacにはないのね。
なので切り替えようがない。

いろいろ悩んだが、これはMacVNC viewerの側で解決できた。

VNC viewerのPreferenceで
f:id:k-kuro:20190421193244p:plain
このようにLeftCmdKeyをSuper_Lに、LeftOptKeyをAlt_Lに設定してやると良い。
ちなみにデフォルトではLeftCmdKeyがAlt_Lに設定されている。
まあこの辺はWindowsのキーボードのWinキーとAltキーの並び順に従っているのだろうけど、macのoptionキーにはAltと表示されているんだがな。でsuperキーを設定せずに放置しているのってどういうことよ、って思うね。

なおSSHVNCの端末はUSキーボードだからといってlocalectlでキーボードレイアウトをUSにしておく必要はないようだ。localectlでは直接サーバにつないだキーボードの設定を変えるコマンドで、SSHVNCで接続した場合はそれぞれの端末でキーボードレイアウトを読み取って送信しているのだね。


なお、日本語のコピペが文字化けるのは仕様のようで。

サーバのメモリ構成を整理

サーバ   CPU                メモリ              理論性能
RX1330M3 E3-1230v6(4C/8T, 3.50GHz)    2400 UDIMM 64GB       224.0GFLOPS
RX300S7  E5-2667(6C/12T, 2.90GHz)x2   1600 LV-RDIMM 32GB      278.4GFLOPS
RX300S7  E5-2643(4C/8T, 3.30GHz)x2   1600 LV-UDIMM 24GB      211.2GFLOPS
RX200S7  E5-2620(6C/12T, 2.00GHz)x2   1333 RDIMM 22GB       192.0GFLOPS
RX200S6  E5630(4C/8T, 2.50GHz)x2    1333 RDIMM 24GB       80.0GFLOPS
RX200S6  E5630(4C/8T, 2.50GHz)x2    1333 UDIMM 4GB       80.0GFLOPS   #バックアップ機
以上クラスタ

RX300S7  E5-2630L(6C/12T, 2.00GHz)   1600 LV-RDIMM 16GB     96.0GFLOPS  GeForce GT 710  #GPU test機

S6世代の使用頻度が下がってきていたので24GBのRDIMM(PC3-10600R)をRX200S7に移し、RX200S7に入れていた16GBのLV-RDIMMをGPU機に。
とりあえずの感じで付いていた4GB UDIMM(PC3-10600E)をRX200S6に入れて、バックアップ機とすることにした。
いっそこのS6はクラスタから外して、CPUも元々付いていたE5603 x1に戻しちゃってNASとして運用しようかな。無駄に電気食いすぎるか?
むしろこのRX200S6にGPUを乗っけてdeep learningに回すのがいいかも。そもそもRX300S7にCPUをもう一個乗っけてしまえば、S62台分をまかなえちゃうのな。クラスタは台数減らしたほうが管理はしやすいのでそのほうがいいかも。



備考
E56xx系統 Nehalem-EP, Westmere-EP のFLOPS/CLOCK は4
E5-26xx系統 Sandy BridgeのFLOPS/CLOCKは8
E3-1230v6系統 Kaby LakeのFLOPS/CLOCKは16

富士通PRIMERGY RX300S7で深層学習の学習環境を構築してみる(2)

続き

次にanacondaを入れる
最初普通にanacondaのサイトからインストーラをダウンロードしてきて

$ bash Anaconda3-5.3.1-Linux-x86_64.sh

とインストールしてtensorflowをpipで入れて・・・とやってみたのだが、glibcのバージョンがCentOS7では2.17、tensorflowが2.23を要求するということからドツボにはまり、glibcを別途用意してLD_LIBRARY_PATHで指定して、とか頑張ってみたのだが、今ひとつすっきりしないし、systemを破壊しそうでナニだったことから、anaconda自体をpyenvで隔離することにした。

anaconda はpyenvのもとにインストールし、systemのpython2.7もしくはpython3とは切り離しておく

$ git clone https://github.com/yyuu/pyenv.git ~/.pyenv
$ echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bashrc
$ echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bashrc
$ echo 'eval "$(pyenv init -)"' >> ~/.bashrc
$ source ~/.bashrc

anacondaは最新版をインストール

$ pyenv install -l | grep anaconda

$ pyenv install anaconda3-5.3.1
$ pyenv rehash

$ pyenv global anaconda3-5.3.1 # anacondaをpythonのデフォルトに設定
$ echo 'export PATH="$PYENV_ROOT/versions/anaconda3-5.3.1/bin/:$PATH"' >> ~/.bashrc
$ source ~/.bashrc

$ conda update conda

CUDA toolkitとcudnnはcondaからインストールできるらしい

$ conda install cudatoolkit
$ conda install cudnn

tensorflow-gpuのインストールなのだが、どうもpython3.7では動かないらしい
TensorFlowをPython3で使う準備をする(Windows10) : としおの読書生活

というわけでanacondaで使うpythonを3.6に落とす。

$ conda install python=3.6

condaを使ってtensorflowをインストール

$ conda install tensorflow-gpu

pythonを起動してtensorflowがちゃんと入ったか確認してみる

$ python
Python 3.6.8 |Anaconda, Inc.| (default, Dec 30 2018, 01:22:34) 
[GCC 7.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from tensorflow.python.client import device_lib
>>> device_lib.list_local_devices()
2019-04-18 09:27:07.652574: I tensorflow/core/platform/cpu_feature_guard.cc:141] Your CPU supports instructions that this TensorFlow binary was not compiled to use: SSE4.1 SSE4.2 AVX
2019-04-18 09:27:07.786044: I tensorflow/core/platform/profile_utils/cpu_utils.cc:94] CPU Frequency: 2000084999 Hz
2019-04-18 09:27:07.792889: I tensorflow/compiler/xla/service/service.cc:150] XLA service 0x564bc4bd80c0 executing computations on platform Host. Devices:
2019-04-18 09:27:07.793038: I tensorflow/compiler/xla/service/service.cc:158]   StreamExecutor device (0): <undefined>, <undefined>
2019-04-18 09:27:08.049509: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:998] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2019-04-18 09:27:08.050256: I tensorflow/compiler/xla/service/service.cc:150] XLA service 0x564bc4cc3680 executing computations on platform CUDA. Devices:
2019-04-18 09:27:08.050307: I tensorflow/compiler/xla/service/service.cc:158]   StreamExecutor device (0): GeForce GT 710, Compute Capability 3.5
2019-04-18 09:27:08.050639: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1433] Found device 0 with properties: 
name: GeForce GT 710 major: 3 minor: 5 memoryClockRate(GHz): 0.954
pciBusID: 0000:03:00.0
totalMemory: 980.94MiB freeMemory: 958.69MiB
2019-04-18 09:27:08.050682: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1512] Adding visible gpu devices: 0
2019-04-18 09:27:08.060169: I tensorflow/core/common_runtime/gpu/gpu_device.cc:984] Device interconnect StreamExecutor with strength 1 edge matrix:
2019-04-18 09:27:08.060206: I tensorflow/core/common_runtime/gpu/gpu_device.cc:990]      0 
2019-04-18 09:27:08.060226: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1003] 0:   N 
2019-04-18 09:27:08.060495: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1115] Created TensorFlow device (/device:GPU:0 with 733 MB memory) -> physical GPU (device: 0, name: GeForce GT 710, pci bus id: 0000:03:00.0, compute capability: 3.5)
[name: "/device:CPU:0"
device_type: "CPU"
memory_limit: 268435456
locality {
}
incarnation: 2232806157292722847
, name: "/device:XLA_CPU:0"
device_type: "XLA_CPU"
memory_limit: 17179869184
locality {
}
incarnation: 16136033629533297001
physical_device_desc: "device: XLA_CPU device"
, name: "/device:XLA_GPU:0"
device_type: "XLA_GPU"
memory_limit: 17179869184
locality {
}
incarnation: 1820044920749343627
physical_device_desc: "device: XLA_GPU device"
, name: "/device:GPU:0"
device_type: "GPU"
memory_limit: 769327104
locality {
  bus_id: 1
  links {
  }
}
incarnation: 12295195253859629574
physical_device_desc: "device: 0, name: GeForce GT 710, pci bus id: 0000:03:00.0, compute capability: 3.5"
]

ちゃんと認識した

さて、環境が整ったっぽいのでkerasも入れてテストしてみよう
kerasのインストール

$ pip install keras

kerasのリポジトリをgit cloneしてmnist_cnn.pyというプログラムを走らせてみる

$ git clone https://github.com/fchollet/keras.git
$ cd keras/examples
$ python mnist_cnn.py
Using TensorFlow backend.
Downloading data from https://s3.amazonaws.com/img-datasets/mnist.npz
11493376/11490434 [==============================] - 5s 0us/step
x_train shape: (60000, 28, 28, 1)
60000 train samples
10000 test samples
WARNING:tensorflow:From /home/kkuro2/.pyenv/versions/anaconda3-5.3.1/lib/python3.6/site-packages/tensorflow/python/framework/op_def_library.py:263: colocate_with (from tensorflow.python.framework.ops) is deprecated and will be removed in a future version.
Instructions for updating:
Colocations handled automatically by placer.
WARNING:tensorflow:From /home/kkuro2/.pyenv/versions/anaconda3-5.3.1/lib/python3.6/site-packages/keras/backend/tensorflow_backend.py:3445: calling dropout (from tensorflow.python.ops.nn_ops) with keep_prob is deprecated and will be removed in a future version.
Instructions for updating:
Please use `rate` instead of `keep_prob`. Rate should be set to `rate = 1 - keep_prob`.
WARNING:tensorflow:From /home/kkuro2/.pyenv/versions/anaconda3-5.3.1/lib/python3.6/site-packages/tensorflow/python/ops/math_ops.py:3066: to_int32 (from tensorflow.python.ops.math_ops) is deprecated and will be removed in a future version.
Instructions for updating:
Use tf.cast instead.
Train on 60000 samples, validate on 10000 samples
Epoch 1/12
2019-04-18 09:35:51.539905: I tensorflow/core/platform/cpu_feature_guard.cc:141] Your CPU supports instructions that this TensorFlow binary was not compiled to use: SSE4.1 SSE4.2 AVX
2019-04-18 09:35:51.551448: I tensorflow/core/platform/profile_utils/cpu_utils.cc:94] CPU Frequency: 2000084999 Hz
2019-04-18 09:35:51.552561: I tensorflow/compiler/xla/service/service.cc:150] XLA service 0x56298dfd6eb0 executing computations on platform Host. Devices:
2019-04-18 09:35:51.552623: I tensorflow/compiler/xla/service/service.cc:158]   StreamExecutor device (0): <undefined>, <undefined>
2019-04-18 09:35:51.683502: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:998] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2019-04-18 09:35:51.684277: I tensorflow/compiler/xla/service/service.cc:150] XLA service 0x56298e0c23d0 executing computations on platform CUDA. Devices:
2019-04-18 09:35:51.684383: I tensorflow/compiler/xla/service/service.cc:158]   StreamExecutor device (0): GeForce GT 710, Compute Capability 3.5
2019-04-18 09:35:51.684947: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1433] Found device 0 with properties: 
name: GeForce GT 710 major: 3 minor: 5 memoryClockRate(GHz): 0.954
pciBusID: 0000:03:00.0
totalMemory: 980.94MiB freeMemory: 958.69MiB
2019-04-18 09:35:51.685056: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1512] Adding visible gpu devices: 0
2019-04-18 09:35:51.686590: I tensorflow/core/common_runtime/gpu/gpu_device.cc:984] Device interconnect StreamExecutor with strength 1 edge matrix:
2019-04-18 09:35:51.686655: I tensorflow/core/common_runtime/gpu/gpu_device.cc:990]      0 
2019-04-18 09:35:51.686696: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1003] 0:   N 
2019-04-18 09:35:51.687099: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1115] Created TensorFlow device (/job:localhost/replica:0/task:0/device:GPU:0 with 733 MB memory) -> physical GPU (device: 0, name: GeForce GT 710, pci bus id: 0000:03:00.0, compute capability: 3.5)
2019-04-18 09:35:57.798268: I tensorflow/stream_executor/dso_loader.cc:152] successfully opened CUDA library libcublas.so.10.0 locally
  128/60000 [..............................] - ETA: 1:30:39 - loss: 2.2983 - acc  256/60000 [..............................] - ETA: 45:50 - loss: 2.2962 - acc: 

(中略)

59776/60000 [============================>.] - ETA: 0s - loss: 0.0267 - acc: 0.959904/60000 [============================>.] - ETA: 0s - loss: 0.0269 - acc: 0.960000/60000 [==============================] - 76s 1ms/step - loss: 0.0271 - acc: 0.9917 - val_loss: 0.0344 - val_acc: 0.9881
Test loss: 0.03438230963442984
Test accuracy: 0.9881

という感じにテスト完了。ちゃんと機能しているっぽい。

epoch=20の学習によって損失値が
loss: 2.2962
loss: 0.0271
と下がっていることがわかる。

めでたしめでたし

batch_size = 128
num_classes = 10
epochs = 12

GPUあり00:15:28

GPU有り無しでどの程度違うのかはテストしてみないとな
ただ、GT710のメモリ1Gではちょっと足らないっぽいな。Running low on GPU memoryって警告が出っぱなしで、相当足を引っ張ってたっぽい
f:id:k-kuro:20190419101052p:plain


追記
ちなみにCPUの方は6core/12threadあるけど、1コア分しか働いてないね。サーバ本体のメモリは4GBしか積んでないけど、64%使用程度なので、十分らしい。
f:id:k-kuro:20190419101752p:plain

あえてGPUを使わずCPUだけを使って行うときは

$ export CUDA_VISIBLE_DEVICES=""

というふうにする

epoch=1でテストランしてみたところ
GPUあり:79秒
GPUなし:108秒
36%の高速化(w
と流石にローエンドGPUだけあって差はそんなもんか、というレベルだった。
#こりゃ手持ちの6core/12thread x 2のサーバでCPUだけでやったほうが速いんちゃう?
GPUメモリ不足が致命的なのかな。batch_sizeを下げるとかチューニングが必要なのかも


なお、GPUなしで走らせると
f:id:k-kuro:20190419105829p:plain
確かにCPUがフル回転している

終わったら

unset CUDA_VISIBLE_DEVICES

GPU使う設定に戻しておく

富士通PRIMERGY RX300S7で深層学習の学習環境を構築してみる

データ解析をする上で無視できない深層学習(deep learning)を使えるように勉強中なのだが、手元に実機があったほうがいろいろと試せて良いだろう、ということでサーバの1ノードを深層学習用GPUマシンにすることにした。
当初RX200S7 (XEON E5-2620 x2)の1UサーバにGPUを乗っけてテストを開始したのだが、流石に1Uでは窮屈かなと、2UのRX300S7 (XEON E5-2630L)を入手してみた。
#春は中古サーバが安く出回っていいね。
本当は2UだとフルハイトのPCIカードが刺さらないので、タワー型のサーバ機のほうが良いのだけど、そういう汎用性のありそうな機械はヤフオクでも結構値がつり上がっちゃうので、やむなく2Uラックサーバで我慢する。
GPUは画像を表示させるわけでもないのでx16フルに繋がっている必要はないから、仮想通貨マイナー御用達の外付けx1 PCI-eの基板などで外付けにすればいいのだろうが(そうするとRX300でなくてもいいとも言えるが)、とりあえずはテスト環境として、一番安価でCUDA対応しているNVIDIA GeForce GT710というロープラファイルでローエンドなグラフィックボードを入れてみた。

まずはいろいろとサイトを巡って情報収集。
いつもお世話になっています
CentOS 7 : CUDA 9.1 インストール : Server World
まずはここを参考にCUDAをインストールしてみる。

このページではCUDA9.1を入れているが、こういう情報はすぐに更新されていってしまうので、そのままやるという訳にはいかない。
そもそもいろいろ関係するもののバージョンの組み合わせによって動いたり動かなかったりするわけで、いつの間にか情報のあるバージョンがダウンロードできなくなっていたりするので厄介だ。かといってすべて最新バージョンにしたらだいたいはうまくいかないというのがこの世界。試行錯誤するしか無いのな。

2019年4月18の段階の各種最新バージョンは以下の通り
anaconda3-5.3.1
python 3.7.2
tensorflow-gpu-1.13.1
CUDA-10.1
nvidia-driver-418.43

まずはグラボをインストール。RX300S7のマニュアルを見るとグラボはPCI-slot5に挿せ、とあったので素直に従ってみたところ認識しないし。マニュアルをよくよく見てみると、slot5,6は2CPUでないと使えないとか書いてるし。どういうこっちゃ。結局グラボの装着順は(1) slot5, (2) slot4ということらしく、1CPUのときは(1)は飛ばして(2) slot4に挿す必要があるようで、わかりにくいことこの上ない。ついでにグラボを挿すとオンボードVGAは使えなくなるというおまけ付き。

とりあえずnvidiaのドライバを入れるために標準ドライバを切る。

# lsmod | grep nouveau
nouveau 1869689 0
mxm_wmi 13021 1 nouveau
video 24538 1 nouveau
wmi 21636 2 mxm_wmi,nouveau
drm_kms_helper 179394 2 mgag200,nouveau
ttm  114635 2 mgag200,nouveau
drm  429744 5 ttm,drm_kms_helper,mgag200,nouveau
i2c_algo_bit  13413 3 igb,mgag200,nouveau
# nano /etc/modprobe.d/blacklist-nouveau.conf
# cat /etc/modprobe.d/blacklist-nouveau.conf
blacklist nouveau
options nouveau modeset=0

# dracut --force
# reboot

次にドライバをインストール

必要なパッケージをインストール

# yum -y install kernel-devel-$(uname -r) kernel-header-$(uname -r) gcc make

インストールされているグラボを確認

# lspci | grep VGA
04:00.0 VGA compatible controller: NVIDIA Corporation GK208B [GeForce GT 710] (rev a1)
08:00.0 VGA compatible controller: Matrox Electronics Systems Ltd. MGA G200e [Pilot] ServerEngines (SEP1) (rev 05)

ドライバをダウンロード

# wget http://jp.download.nvidia.com/XFree86/Linux-x86_64/418.43/NVIDIA-Linux-x86_64-418.43.run

インストール

# bash NVIDIA-Linux-x86_64-418.43.run
Verifying archive integrity... OK
Uncompressing NVIDIA Accelerated Graphics Driver for Linux-x86_64 418.43................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................

途中のメッセージはすべてyesで進む
f:id:k-kuro:20190617124038p:plain

f:id:k-kuro:20190617124053p:plain

f:id:k-kuro:20190617124104p:plain
ちゃんと入ったか確認

# nvidia-smi

+-----------------------------------------------------------------------------+
| NVIDIA-SMI 418.43  Driver Version: 418.43   |
|-------------------------------+----------------------+----------------------+
| GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC |
| Fan Temp Perf Pwr:Usage/Cap|  Memory-Usage | GPU-Util Compute M. |
|===============================+======================+======================|
|  0 GeForce GT 710 Off | 00000000:04:00.0 N/A | N/A |
| 50%  28C P0 N/A / N/A | 0MiB /  980MiB |  N/A Default |
+-------------------------------+----------------------+----------------------+
+-----------------------------------------------------------------------------+
| Processes:  GPU Memory |
| GPU  PID  Type  Process name  Usage |
|=============================================================================|
| 0 Not Supported  |
+-----------------------------------------------------------------------------+

Not Supportedは気になるが、ローエンド機種なのでそういうものらしい

続いてCUDA10.1をダウンロードしてインストール

# wget https://developer.download.nvidia.com/compute/cuda/repos/rhel7/x86_64/cuda-repo-rhel7-10.1.105-1.x86_64.rpm
# rpm -Uvh cuda-repo-rhel7-10.1.105-1.x86_64.rpm
# sed -i -e "s/enabled=1/enabled=0/g" /etc/yum.repos.d/cuda.repo
# yum --enablerepo=cuda,epel install cuda-10-1 xorg-x11-drv-nvidia dkms gcc make

いろいろ情報を見てもCUDA10.0までしか実績はなさそうだけど
gcc, makeはすでに最新版だったらしくインストールはされないのはいいが、DKMSのインストールでコケた

# rpm -Uvh https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
# yum --enablerepo=cuda,epel install cuda-10-1 xorg-x11-drv-nvidia dkms

とすることで回避

# nano /etc/profile.d/cuda101.sh

# cat /etc/profile.d/cuda101.sh
export PATH=/usr/local/cuda-10.1/bin${PATH:+:${PATH}}
export LD_LIBRARY_PATH=/usr/local/cuda-10.1/lib64${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}

ここで一旦再起動

# reboot

一般ユーザでログインして、テストプログラムを走らせてみる

$ cuda-install-samples-10.1.sh ./
Copying samples to ./NVIDIA_CUDA-10.1_Samples now...
Finished copying samples.

$ cd NVIDIA_CUDA-10.1_Samples/1_Utilities/deviceQuery
$ make
$ ./deviceQuery
./deviceQuery Starting...

CUDA Device Query (Runtime API) version (CUDART static linking)

cudaGetDeviceCount returned 35
-> CUDA driver version is insufficient for CUDA runtime version
Result = FAIL

ここでまたエラーが出た。

NVIDIAのドライバを入れ直すと良いらしい

# bash NVIDIA-Linux-x86_64-418.43.run

改めてテスト

$ cd NVIDIA_CUDA-10.1_Samples/1_Utilities/deviceQuery
$ ./deviceQuery
./deviceQuery Starting...

CUDA Device Query (Runtime API) version (CUDART static linking)

Detected 1 CUDA Capable device(s)

Device 0: "GeForce GT 710"
CUDA Driver Version / Runtime Version 10.1 / 10.1
CUDA Capability Major/Minor version number: 3.5
Total amount of global memory:  981 MBytes (1028587520 bytes)
( 1) Multiprocessors, (192) CUDA Cores/MP:  192 CUDA Cores
GPU Max Clock rate: 954 MHz (0.95 GHz)
Memory Clock rate:  800 Mhz
Memory Bus Width: 64-bit
L2 Cache Size:  524288 bytes
Maximum Texture Dimension Size (x,y,z)  1D=(65536), 2D=(65536, 65536), 3D=(4096, 4096, 4096)
Maximum Layered 1D Texture Size, (num) layers 1D=(16384), 2048 layers
Maximum Layered 2D Texture Size, (num) layers 2D=(16384, 16384), 2048 layers
Total amount of constant memory:  65536 bytes
Total amount of shared memory per block:  49152 bytes
Total number of registers available per block: 65536
Warp size:  32
Maximum number of threads per multiprocessor: 2048
Maximum number of threads per block:  1024
Max dimension size of a thread block (x,y,z): (1024, 1024, 64)
Max dimension size of a grid size (x,y,z): (2147483647, 65535, 65535)
Maximum memory pitch: 2147483647 bytes
Texture alignment:  512 bytes
Concurrent copy and kernel execution: Yes with 1 copy engine(s)
Run time limit on kernels:  No
Integrated GPU sharing Host Memory: No
Support host page-locked memory mapping:  Yes
Alignment requirement for Surfaces: Yes
Device has ECC support: Disabled
Device supports Unified Addressing (UVA): Yes
Device supports Compute Preemption: No
Supports Cooperative Kernel Launch: No
Supports MultiDevice Co-op Kernel Launch: No
Device PCI Domain ID / Bus ID / location ID:  0 / 4 / 0
Compute Mode:
< Default (multiple host threads can use ::cudaSetDevice() with device simultaneously) >

deviceQuery, CUDA Driver = CUDART, CUDA Driver Version = 10.1, CUDA Runtime Version = 10.1, NumDevs = 1
Result = PASS

これでCUDAはちゃんとインストールできたっぽい
続く

PCAやMDS plotをpythonで行う

これまでPCAやMDSをやりたいときはRを使っていた。しかしRはどうも肌に合わない。すぐ忘れてしまう。
ということでここはやはりPythonですね、ってことでどうやるのか調べてみた。

【python】pca、mds、nmds、tsneとmatplotlibでデータの可視化をしてみる - 静かなる名辞

[Python]PythonでPCAを行う方法 - Qiita

ほおほお、scikit-learnを使えばいいのね。機械学習の環境構築を最近したばっかりなので、すでに環境は整ってるじゃないの。
ということで早速取り掛かる。

とにかくscikit-learnからライブラリを読み込む

from sklearn.decomposition import PCA

データを読み込む(csvから読み込めば簡単)

import numpy as np
npArray = np.loadtxt("analysis.csv", delimiter = ",")
X = np.array(npArray)

実行する

pca = PCA(n_components=2)
pca.fit(X)

以上!
という簡単さ。なにこれ。
あとはmatplotlibでグラフにすれば一丁上がり。

# coding: UTF-8
 
import numpy as np
from matplotlib import pyplot as plt
from sklearn.decomposition import PCA
from sklearn.manifold import MDS, TSNE

def main():
    npArray = np.loadtxt("analysis.csv", delimiter = ",")
    X = np.array(npArray)

    pca = PCA()
    pca.fit(X)    
    transformed = pca.fit_transform(X)
    plt.scatter(transformed[:, 0], transformed[:, 1])
    plt.title('principal component')
    plt.xlabel('pc1')
    plt.ylabel('pc2')
    print(pca.explained_variance_ratio_)    
    plt.show()

    mds = MDS(n_jobs=4)
    mds.fit(X)  
    transformed = mds.fit_transform(X)
    plt.scatter(transformed[:, 0], transformed[:, 1])
    plt.title('Multidimensional scaling')
    plt.show()
    
    tsne = TSNE()
    tsne.fit(X)    
    transformed = tsne.fit_transform(X)
    plt.scatter(transformed[:, 0], transformed[:, 1])
    plt.title('t-distributed Stochastic Neighbor embedding')
    plt.show()
   
if __name__ == '__main__':
    main()   

MDS plotやtSNEも数行書き換えるだけでOK