概要
2018年に出題されていた某コンペの衛星画像の識別コンペの、データだけ取ってあったのでそれで遊んでみる。
環境
GCP 上にインスタンスを用意。
tensorflow が CUDA9 を要求していて、 CUDA の方は9だと ubuntu 17.10 か 16.04LTS にしかならないので諦めてこれ用に 16.04 でインスタンス作成。
venv 環境で pip インストール。別に scikit-image
も pip でインストールする。
cuDNN も必用なので developer 登録して 7.0.5 の tar ball を取得して /usr/local/
以下に展開。
env LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/usr/local/cuda/lib64 python3 ../files/RdTrn4.py train\_master\_X1.tsv
として利用することにする。
GCPと手元で両方でファイルをいじるので作業ディレクトリはhg管理する。
(hgだとworking directoryであるGCPに直接pushできる)。
GCP上では、 train1.zip を展開して train/
に、train2.zip を展開して test/
にしてある。
train/
で学習してtest/
で答え合わせをする予定。
train_master.tsv
から各々のディレクトリにあるファイルの行だけ抽出してtrain_master_X1.tsv
, test_master.tsv
を作った。
手元でscript修正して確認用に300ファイルだけ手元でも展開してtrain_master_mini.tsv
も作成。
結局こんな抽出scriptを書いた。
# ! /usr/bin/env python
import sys, os
if __name__ == '__main__':
if len(sys.argv) > 2:
f = open(sys.argv[1])
filenames0 = f.readlines()
f.close()
header = filenames0.pop(0)
filenamedic = {}
for l in filenames0:
ll = l.split()
filenamedic[ll[0]] = l
filenames2 = os.listdir(sys.argv[2])
print(header.strip())
for l in filenames2:
print(filenamedic[l].strip())
else:
print('command filename dir/')
script
去年時点でこんな script 書いて動かすところまではやっていた。
チュートリアルにあった MNIST の CNN の丸コピー。
100ファイル取ってきて1バッチとして50回イテレーションして次の100ファイルに移って、を繰り返して、全部ファイルを舐めたら1ステップ終了するようにループを組んでいる。
サルベージしてきてこれをベースに作業を進める。
# ! /usr/bin/env python
# Read Training Data
# usage
# python RdTrn.py train_master10.tsv
## head -n 11 train_master.tsv > train_master10.tsv
TARGETDIR = 'Train_all/'
BATCHSIZE=100
MODE2='CONT'
# MODE2='RESET'
NUM_STEP = 50
SHUFFLE=True
# CNN
# [32,32,7]pixel -> [5,5,7,16] kernel -> [32,32,16]pixel -> [16,16,16]pixel
# -> [3,3,16,32] kernel -> [16,16,32]pixel -> [8,8,32]pixel -> [512]FC
import tensorflow as tf
def weight_variable(shape):
initial = tf.truncated_normal(shape, stddev=0.1)
return tf.Variable(initial)
def bias_variable(shape):
initial = tf.constant(0.1, shape=shape)
return tf.Variable(initial)
def conv2d(x, W):
return tf.nn.conv2d(x, W, strides=[1,1,1,1], padding='SAME')
def max_pool_2x2(x):
return tf.nn.max_pool(x, ksize=[1,2,2,1], strides=[1,2,2,1], padding='SAME')
x = tf.placeholder(tf.float32, shape=[None, 32,32,7])
y_ = tf.placeholder(tf.float32, shape=[None,2])
# x_image = x / 256.0
x_image = x
## 1st layer
W_conv1 = weight_variable([5,5,7,16])
b_conv1 = bias_variable([16])
h_conv1 = tf.nn.relu(conv2d(x_image, W_conv1) + b_conv1)
h_pool1 = max_pool_2x2(h_conv1)
## 2nd layer
W_conv2 = weight_variable([3,3,16,32])
b_conv2 = bias_variable([32])
h_conv2 = tf.nn.relu(conv2d(h_pool1, W_conv2) + b_conv2)
h_pool2 = max_pool_2x2(h_conv2)
## 3rd, full-connection
W_fc1 = weight_variable([8 * 8 * 32, 512])
b_fc1 = bias_variable([512])
h_pool2_flat = tf.reshape(h_pool2, [-1, 8*8*32])
h_fc1 = tf.nn.relu(tf.matmul(h_pool2_flat, W_fc1) + b_fc1)
keep_prob = tf.placeholder(tf.float32)
h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob)
## 4th,
W_fc2 = weight_variable([512,2])
b_fc2 = bias_variable([2])
y_conv = tf.matmul(h_fc1_drop, W_fc2) + b_fc2
residual = y_ - y_conv
residual2 = tf.nn.softmax_cross_entropy_with_logits(labels=y_, logits=y_conv)
cross_entropy = tf.reduce_mean(
tf.nn.softmax_cross_entropy_with_logits(labels=y_, logits=y_conv))
train_step = tf.train.AdamOptimizer(1e-4).minimize(cross_entropy)
correct_prediction = tf.equal(tf.argmax(y_conv, 1), tf.argmax(y_, 1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
import random
import sys, os
from skimage import io
filenames = []
if os.path.isfile(sys.argv[1]):
MODE = 'TRAIN'
f = open(sys.argv[1])
filenames = f.readlines()
f.close()
filenames.pop(0)
if SHUFFLE:
random.shuffle(filenames)
elif os.path.isdir(sys.argv[1]):
MODE = 'TEST'
filenames = os.listdir(sys.argv[1])
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
saver = tf.train.Saver()
if MODE2 != 'RESET':
if os.path.exists("./model.ckpt.meta"):
saver.restore(sess, "./model.ckpt")
while len(filenames)>0:
filenames_x = filenames[:min(BATCHSIZE, len(filenames))]
del filenames[:min(BATCHSIZE, len(filenames))]
#print(filenames_x, filenames)
if MODE == 'TRAIN':
filenames_y = [l.split()[0] for l in filenames_x]
else:
filenames_y = filenames_x
Train = []
Label = []
for l in filenames_x:
l2 = l.split()
Train.append(io.imread(TARGETDIR+l2[0]))
if MODE == 'TRAIN' and l2[1] == '0':
Label.append([1, 0])
else:
Label.append([0, 1])
a, b = Train[-1].min(), Train[-1].max()
if (b-a > 0):
Train[-1] = (Train[-1] - a) / (b - a)
#print(l2[0],a,b)
else:
Train.pop(-1)
Label.pop(-1)
#print(Train)
#print(Train[0])
#print(Train[0].dtype, Train[0].shape)
print(Label)
Label0 = [[0, 1] for i in Train]
if MODE == 'TRAIN':
for i in range(NUM_STEP):
if i % 10 == 0:
train_accuracy = accuracy.eval(feed_dict={
x: Train, y_: Label, keep_prob: 1.0})
print('step %d, training accuracy %g' % (i, train_accuracy))
#print(residual2.eval(feed_dict={
# x: Train, y_: Label, keep_prob: 1.0}))
train_step.run(feed_dict={x: Train, y_: Label, keep_prob: 0.5})
#print(y_conv.eval(feed_dict={
# x: Train, y_: Label, keep_prob: 1.0}))
print(residual2.eval(feed_dict={
x: Train, y_: Label, keep_prob: 1.0}))
answer = correct_prediction.eval(feed_dict={
x: Train, y_: Label0, keep_prob: 1.0})
for i in range(len(answer)):
print(filenames_y[i], 0 if answer[i]==False else 1)
saver.save(sess, "./model.ckpt")
とりあえず動くところまでは持って行ってみたが、猛烈に遅い。
上の script の1ステップで4000秒くらいかかる。
とてもやってられない。
何が遅いのかと思って調べてみたら imread が遅い。
imreadを非同期並行処理にできないか調べたが、file readがコルーチンでないので無理そう。
こんなに遅いんじゃ機械学習成立しないじゃんみんなどうしてんだ?
調べてみるとgcpの通常のディスクは 0.75 IOPS という説
アクセスが激しい用途なら別に SSD を増設しておかないとダメっぽい
SSD上にデータを置いて
1回学習データに対して、
判定・学習・判定
> tail -n 2 results.0218*
==> results.0218 <==
read 310.85166597366333 compute 8.858093976974487
read 302.8673777580261 7.035254001617432
==> results.0218_2 <==
read 314.44825434684753 compute 537.2505786418915
read 306.3731019496918 7.047821760177612
==> results.0218_3 <==
read 325.11989974975586 compute 14.689516067504883
read 317.0948975086212 7.06338095664978
HDD 時代の1回学習に対する判定
read 3403.6323153972626 compute 17.437681198120117
read 3393.889718055725 8.453051567077637
read | compute | IoU | |
---|---|---|---|
学習1(HDD) | (4112) | 0.946 | |
判定1(HDD) | 3403.63 | 17.43 | |
判定1(SSD) | 310.85 | 8.85 | 0.521 |
学習2 | 314.45 | 537.25 | 0.964 |
判定2 | 325.12 | 14.69 | 0.576 |
3000秒が300秒になったのでよしとする。
学習に使ったデータに対しては高い正答率が出るのに、未知データだと正答率が低いんでそれっぽいなーという感じ。