読者です 読者をやめる 読者になる 読者になる

ytbilly3636’s 研究備忘録

機械学習,Python,ガンダムなど

トマトダイエットを試した

こんにちは.

先日テレビでトマトを食べるだけで痩せるという内容の番組が放送されておりまして, 本当かどうかを自らの身体を使って実験をしてみました,というお話です.

f:id:ytbilly3636:20170515113209j:plain

トマトのフリー写真素材 Page1|食材・料理の無料画像 フード・フォト

やったこと

トマトダイエットのルールは晩御飯を食べる前にトマトを2つ食べるだけだそうです. それ以外は特に制約はなく,何を食べても良いし,私の場合たまに間食もとりました. また,トマトは加熱するなどの調理をしても良いそうです.

トマトを食べると基礎代謝が上がるので痩せやすくなるだとか, トマト2つ分の水分で満腹になるので晩御飯の量が減り痩せやすくなるとかいう理由があるようです. そのあたりは詳しくないので,正確なことはわかりません.

結果

3週間ほど続けた結果,以下のように体重が遷移していきました. 縦軸が[kg]で横軸が経過日数です. 実線が実際の体重で,破線が線形近似です.

f:id:ytbilly3636:20170515114115p:plain

9日目に急激に体重が増えたのは,飲み会に参加したためと考えられます. 11~12日目くらいに急に体重が落ち,リバウンドもしませんでした. トマトを食べるだけという最低限の努力でそれなりに痩せる事ができたと思います.

感想

トマトダイエットは運動の必要はないですし楽は楽なのですが,それなりの辛さがありました.

  • 生トマト丸かじりはすぐ飽きる
  • トマトだけで満腹になるのはなんか悔しい
  • トマト料理のレパートリーが尽きる
  • トマトが高い

特にレパートリーには苦しめられました. 結局,トマトパスタばかり食べていたような気がします.

www.youtube.com

繰り返しにはなりますが,トマトダイエットにはそれなりの効果があると思います. 続けるのもそこまで難しくはないので,試してみてはいかがでしょうか.

Chainerで畳み込みのAutoencoderを実装した

こんにちは

ChainerのReference ManualにDeconvolution2Dというクラスが有るのを見つけました.

Standard Link implementations — Chainer 1.23.0 documentation

Deconvolutionってなんぞと思い,調べると以下のページが見つかりました.

qiita.com

特徴マップを拡大して畳み込むことで,畳み込む前の画像を復元するイメージでしょうか. ということは,

Input -> Convolution -> Feature Maps -> Deconvolution -> Output

という処理を行えば, Autoencoder畳み込みバージョンができるのではないかと思い試してみました. いわゆる,Convolutional Autoencoderはこのような実装なんですかね. 調べていないのでなんとも言えませんが.

環境

項目 詳細
OS Ubuntu 14.04
GPU GTX 970
Ver Chainer 1.18.0

コード

可視化のためOpenCVとmatplotlibを用いています. 高速化のためGPUを用いています.

# -*- coding: utf-8 -*-

import sys, os, cv2
import numpy as np
import matplotlib.pyplot as plt
import chainer
import chainer.links as L
import chainer.functions as F
from chainer import cuda, Variable, optimizers, Chain, datasets

# 畳み込みAutoencoderの定義
class CAE(Chain):
    # 入力は3チャンネルのカラー画像を想定しているので入出力を3チャンネルに
    def __init__(self, num_filter, size_filter):
        super(CAE, self).__init__(
            conv1 = L.Convolution2D(3, num_filter, size_filter),
            dcnv1 = L.Deconvolution2D(num_filter, 3, size_filter),
        )
        return
    
    # 活性化関数はReLU    
    def __call__(self, x):
        f1 = F.relu(self.conv1(x))
        f2 = F.relu(self.dcnv1(f1))
        return f2

    # 損失関数はL2ノルムとした  
    def loss(self, x):
        return F.mean_squared_error(self.__call__(x), x)


# 最適化手法:Adam        
cae = CAE(num_filter=16, size_filter=5)
opt = optimizers.Adam()
opt.setup(cae)
cae.to_gpu()


# CIFAR10を学習
train, test = datasets.get_cifar10()


# 1epoch分の学習
def train_epoch(batch_size):
    # グラフ描画用のarray
    x_graph = np.arange(0, train._length / batch_size)
    y_graph = np.zeros(train._length / batch_size)

    # batch_size分の画像をtrain._length/batch_size回に分けてミニバッチ学習
    perm = np.random.permutation(train._length)
    for i in xrange(0, train._length, batch_size):
        x_batch = Variable(cuda.to_gpu(cuda.cupy.asarray(train[perm[i:i+batch_size]][0], dtype=cuda.cupy.float32)))
        
        # 損失の計算・逆伝播・更新
        cae.zerograds()
        loss = cae.loss(x_batch)
        loss.backward()
        opt.update()
        
        # 損失をグラフに描画
        y_graph[i / batch_size] = loss.data
        plt.clf()
        plt.title('loss')
        plt.plot(x_graph, y_graph)
        plt.pause(.01)
        
        # test[0][0]をエンコードしてデコードしたものを可視化
        encode_and_decode(number=0)
    return


# エンコードしてデコードしたものを表示
def encode_and_decode(number):
    x = Variable(cuda.to_gpu(cuda.cupy.asarray(test[number][0], dtype=cuda.cupy.float32).reshape(1, 3, 32, 32)))   
    y = cae(x)

    # OpenCVの形式に合わせる
    x_data = cv2.cvtColor(np.rollaxis(cuda.to_cpu(x.data).reshape(3, 32, 32), 0, 3), cv2.COLOR_RGB2BGR)
    y_data = cv2.cvtColor(np.rollaxis(cuda.to_cpu(y.data).reshape(3, 32, 32), 0, 3), cv2.COLOR_RGB2BGR)

    cv2.imshow("origin:" + str(number), cv2.resize(x_data, (200, 200)))
    cv2.imshow("result:" + str(number), cv2.resize(y_data, (200, 200)))
    cv2.waitKey(1)
    return


# 実行    
train_epoch(batch_size=100)

更新とともに,画像が復元できていくのを確認できると思います.

f:id:ytbilly3636:20170514211629j:plain
学習回数:0

f:id:ytbilly3636:20170514211718j:plain
学習回数:5000

f:id:ytbilly3636:20170514211738j:plain
学習回数:45000

ちなみに入力画像はこんな感じでした.
f:id:ytbilly3636:20170514211824j:plain

簡単な解説

CAEクラス

今回の一番のポイントはこのクラスです.

class CAE(Chain):
    def __init__(self, num_filter, size_filter):
        super(CAE, self).__init__(
            conv1 = L.Convolution2D(3, num_filter, size_filter),
            dcnv1 = L.Deconvolution2D(num_filter, 3, size_filter),
        )
        return
    
    def __call__(self, x):
        f1 = F.relu(self.conv1(x))
        f2 = F.relu(self.dcnv1(f1))
        return f2

    def loss(self, x):
        return F.mean_squared_error(self.__call__(x), x)

L.Convolution2D,及びL.Deconvolution2Dの引数は順に,入力の枚数,特徴マップ(出力)の数,フィルターのサイズです. 今回の場合3チャンネルの画像を畳み込んで16枚の特徴マップを出力し,16枚の特徴マップを逆畳み込みして3枚の出力, すなわち3チャネルのカラー画像を出力するようにしています.

損失関数はネットワークの出力と教師信号(すなわち入力画像)とのL2ノルムで求めています. これはF.mean_squared_errorを使えば簡単に求めることができます.

学習

1バッチ分の学習は以下のコードによって行われます.

cae.zerograds()
loss = cae.loss(x_batch)
loss.backward()
opt.update()

損失lossを求めて,それを逆伝播させて,optimizersで更新するだけです.

1バッチ分の入力はどうやって作ってもよいと思いますが, この方法が一番簡単かと思います.

# 0~49999の数字をランダムに並び替えた配列を用意
perm = np.random.permutation(train._length)

# permの0~99番目,100~199番目,…というように選んでいく
for i in xrange(0, train._length, batch_size):
    x_batch = Variable(cuda.to_gpu(cuda.cupy.asarray(train[perm[i:i+batch_size]][0], dtype=cuda.cupy.float32)))
    

CPU版の場合,cuda.cupyをnpに変えてcuda.to_gpuを削除したらよいと思います.

可視化

私はここで少し詰まりました. 今回GPUを使っているので,入力データであるxと出力データであるyは(多分)GPUのメモリにあります. これをnumpy.arrayとして扱いたい場合は一旦cuda.to_cpuをかましてやる必要があります.

x = Variable(cuda.to_gpu(cuda.cupy.asarray(test[number][0], dtype=cuda.cupy.float32).reshape(1, 3, 32, 32)))   
y = cae(x)
x_data = cv2.cvtColor(np.rollaxis(cuda.to_cpu(x.data).reshape(3, 32, 32), 0, 3), cv2.COLOR_RGB2BGR)
y_data = cv2.cvtColor(np.rollaxis(cuda.to_cpu(y.data).reshape(3, 32, 32), 0, 3), cv2.COLOR_RGB2BGR)

Caffe2を使ってみたその2「MNISTの学習」

こんにちは.

今回の記事ではCaffe2を使ってLeNetを実装し,MNISTを学習させてみます. 方法については公式のチュートリアルを参照(というよりそのままです)しました.

MNIST - Create a CNN from Scratch | Caffe2

環境

項目 詳細
OS Ubuntu 14.04
GPU GTX970

データセットの用意

Caffe2ではCaffeの時と同様, 学習画像のデータベースを用意しておき, データベースから読み込んでいきます.

下記サイトから4つのファイルをダウンロードします.

http://yann.lucan.com/exdb/mnist/

  • train-images-idx3-ubyte.gz
  • train-labels-idx1-ubyte.gz
  • t10k-images-idx3-ubyte.gz
  • t10k-labels-idx1-ubyte.gz

ダウンロードしたファイルを解凍し,Caffe2のコマンドによってデータベース化していきます.

$ gunzip train-images-idx3-ubyte.gz
$ gunzip train-labels-idx1-ubyte.gz
$ gunzip t10k-images-idx3-ubyte.gz
$ gunzip t10k-labels-idx1-ubyte.gz

# 解凍したファイルはホームフォルダに置いたとする.
$ cd caffe2
$ mkdir -p caffe2/python/tutorials/tutorial_data/mnist/
$ ./build/caffe2/binaries/make_mnist_db --channel_first --db leveldb --image_file ~/train-images-idx3-ubyte --label_file ~/train-labels-idx1-ubyte --output_file caffe2/python/tutorials/tutorial_data/mnist/mnist-train-nchw-lebeldb
$ ./build/caffe2/binaries/make_mnist_db --channel_first --db leveldb --image_file ~/t10k-images-idx3-ubyte --label_file ~/t10k-labels-idx1-ubyte --output_file caffe2/python/tutorials/tutorial_data/mnist/mnist-test-nchw-lebeldb

スクリプトの用意

Caffe2ではCaffeとは異なりprototxtを用意せずとも, Pythonスクリプト1つで学習の記述ができるようです.

# -*- coding: utf-8 -*-

# 読み込むモジュール
import numpy as np, os, shutil
from   matplotlib import pyplot
from   caffe2.python import core, cnn, net_drawer, workspace, visualize


# 初期化
core.GlobalInit(['caffe2', '--caffe2_log_level=0'])
caffe2_root = '~/caffe2'


# パスのオプション
# 適宜書き換えてください!
data_folder = '/home/username/caffe2/caffe2/python/tutorials/tutorial_data/mnist'


# ネットワークの入力
def AddInput(model, batch_size, db, db_type):
    # DBからデータ(画像、ラベル)の読み込み
    data_uint8, label = model.TensorProtosDBInput(
        [], ['data_uint8', 'label'], batch_size=batch_size, db=db, db_type=db_type
    )
    
    # データ型の変換: uint8 -> float
    data = model.Cast(data_uint8, "data", to=core.DataType.FLOAT)
    
    # スケールの変更: [0 255] -> [0 1]
    data = model.Scale(data, data, scale=float(1./256))
    
    # 逆伝播時に微分の計算をしない(入力だから)
    data = model.StopGradient(data, data)
    
    return data, label
    
    
# ネットワークの本体
def AddLeNetModel(model, data):
    # conv -> pool -> conv -> pool -> Relu(fc) -> SoftMax(fc)
    
    # NxCxHxW: 1x1x28x28 -> 20x1x24x24 -> 20x1x12x12
    conv1 = model.Conv(data, 'conv1', 1, 20, 5)
    pool1 = model.MaxPool(conv1, 'pool1', kernel=2, stride=2)
    
    # NxCxHxW: 20x1x12x12 -> 50x1x8x8 -> 50x1x4x4
    conv2 = model.Conv(pool1, 'conv2', 20, 50, 5)
    pool2 = model.MaxPool(conv2, 'pool2', kernel=2, stride=2)
    
    # NxCxHxW: 800x1x1x1 -> 500x1x1x1
    fc3   = model.FC(pool2, 'fc3', 50 * 4 * 4, 500)
    fc3   = model.Relu(fc3, fc3)
    
    # NxCxHxW: 500x1x1x1 -> 10x1x1x1
    pred  = model.FC(fc3, 'pred', 500, 10)
    softmax = model.Softmax(pred, 'softmax')
    
    return softmax
    
    
# ネットワークの正解率
def AddAccuracy(model, softmax, label):
    accuracy = model.Accuracy([softmax, label], 'accuracy')
    return accuracy
    
    
# 学習
def AddTrainingOperators(model, softmax, label):
    # クロスエントロピーの計算
    xent = model.LabelCrossEntropy([softmax, label], 'xent')
    
    # クロスエントロピーの平均損失の計算
    loss = model.AveragedLoss(xent, 'loss')
    
    # 正解率の計算
    AddAccuracy(model, softmax, label)
    
    # 損失関数の勾配を計算
    model.AddGradientOperators([loss])
    
    # 学習率の設定(lr = base_lr * (t ^ gamma))
    ITER = model.Iter('iter')
    LR = model.LearningRate(ITER, 'LR', base_lr=-0.1, policy='step', stepsize=1, gamma=0.999)
    
    # 更新に使う定数
    ONE = model.param_init_net.ConstantFill([], 'ONE', shape=[1], value=1.0)
    
    # 全パラメータにおいて更新
    # param = param + param_grad * LR(このような更新式の定義なので,学習率は負値になっている.)
    for param in model.params:
        param_grad = model.param_to_grad[param]
        model.WeightedSum([param, ONE, param_grad, LR], param)
        
    # 20イテレーション毎にチェックポイントを作成
    model.Checkpoint([ITER] + model.params, [], db='mnist_lenet_checkpoint_%05d.leveldb', db_type='leveldb', every=20)
    
    
# ログなどの出力用
def AddBookkeepingOperators(model):
    model.Print('accuracy', [], to_file=1)
    model.Print('loss', [], to_file=1)
    for param in model.params:
        model.Summarize(param, [], to_file=1)
        model.Summarize(model.param_to_grad[param], [], to_file=1)
        
        
# ここからネットワークの準備

# CNNのモデル型を学習用として用意
train_model = cnn.CNNModelHelper(order='NCHW', name='mnist_train')
# データセットの読み込み
data, label = AddInput(train_model, batch_size=64, db=os.path.join(data_folder, 'mnist-train-nchw-leveldb'), db_type='leveldb')
# ネットワークの設定
softmax = AddLeNetModel(train_model, data)
# 学習の設定
AddTrainingOperators(train_model, softmax, label)
# ログの設定
AddBookkeepingOperators(train_model)

# CNNのモデル型をテスト用として用意
test_model = cnn.CNNModelHelper(order='NCHW', name='mnist_test', init_params=False)
# データセットの読み込み
data, label = AddInput(test_model, batch_size=100, db=os.path.join(data_folder, 'mnist-test-nchw-leveldb'), db_type='leveldb')
# ネットワークの設定
softmax = AddLeNetModel(test_model, data)
# 正解率の設定
AddAccuracy(test_model, softmax, label)

# デプロイを用意(何に使うのだろう)
deploy_model = cnn.CNNModelHelper(order='NCHW', name='mnist_deploy', init_params=False)
AddLeNetModel(deploy_model, 'data')


# ここから学習の処理

# ネットワークの初期化
workspace.RunNetOnce(train_model.param_init_net)
workspace.CreateNet(train_model.net)

# pyplot用
total_iters = 200
accuracy = np.zeros(total_iters)
loss     = np.zeros(total_iters)

# 学習
for i in xrange(total_iters):
    workspace.RunNet(train_model.net.Proto().name)
    
    # グラフ描画
    accuracy[i] = workspace.FetchBlob('accuracy')
    loss[i]     = workspace.FetchBlob('loss')
    pyplot.clf()
    pyplot.plot(accuracy, 'r')
    pyplot.plot(loss, 'b')
    pyplot.legend(('loss', 'accuracy'), loc='upper right')
    pyplot.pause(.01)

    
# ここからテストの処理

# ネットワークの初期化
workspace.RunNetOnce(test_model.param_init_net)
workspace.CreateNet(test_model.net)

# pyplot用
test_accuracy = np.zeros(100)

# テスト
for i in range(100):
    workspace.RunNet(test_model.net.Proto().name)
    test_accuracy[i] = workspace.FetchBlob('accuracy')

# グラフ描画
pyplot.plot(test_accuracy, 'r')
pyplot.title('Acuracy over test batches.')
print('test_accuracy: %f' % test_accuracy.mean())

スクリプトの前半部分で関数を定義して, 後半部分でそれらの関数を使ってるイメージです. スクリプトを「train_mnist.py」という名前で保存して,下記コマンドで実行できます.

$ python train_mnist.py

使ってみて思ったこと

Caffeのprototxtよりもネットワークの記述がスッキリしたように思えます. Caffe2独自の書き方に慣れさえすれば,Pythonユーザーにとってはそれほど難しいものではないように思えます. ネットワークが小さいせいか,Caffe2の新機能のおかげなのかはわかりませんが学習はサクサク動きます.

NumPyを使うと幸せになれるかも2: CuPyを使う

こんにちは.

今回の記事はシリーズ第2段です. 厳密に言えばNumPyの話ではなく, Chainerに含まれている行列演算モジュールCuPyの話です.

CuPy解説

CuPyとはNumPyの機能をCUDA上で動かせるというもの. 使い方はnumpyをcupyで置き換えれば良いとのこと. そんなに簡単に使えるのなら使わない手はないと思い, NumPyで実装したあるコードをCuPyで置き換えてみましたが……

遅い……

ということで検証してみました.

環境

項目 詳細
OS Ubuntu 14.04
CPU i5-3570
GPU GTX970

コード

numpyとcuda.cupyの速度を行列積で比較してみました. cuda.cupyは何もしないバージョンとto_gpu()をするバージョンの2つを比較しました.

# -*- coding: utf-8 -*-

import numpy as np
import chainer
import chainer.cuda.cupy as cp
import time

# MNISTを読み込み
# 784次元のベクトル
train, test = chainer.datasets.get_mnist()

s1 = time.time()
np_ar1 = np.array(train[0][0])
np_ar2 = np.array(train[1][0])
a1 = np_ar1.dot(np_ar2.T)

s2 = time.time()
cp_ar1 = cp.array(train[0][0])
cp_ar2 = cp.array(train[1][0])
a2 = cp_ar1.dot(cp_ar2.T)

s3 = time.time()
cp2_ar1 = chainer.cuda.to_gpu(cp.array(train[0][0]))
cp2_ar2 = chainer.cuda.to_gpu(cp.array(train[1][0]))
a3 = cp2_ar1.dot(cp2_ar2.T)

s4 = time.time()
print 'np:',s2-s1
print 'cp:',s3-s2
print 'cp2:',s4-s3
np: 5.57899475098e-05
cp: 0.182370185852
cp2: 0.000236988067627

やはりNumPyが一番速かったです. CuPyが負けてしまったのはGPUへのメモリ転送がネックになっているのだと思います.

あと,numpyをcupyにただ置き換えるだけではなく, to_gpu()を書いてあげたほうがいいみたいです.

ちなみに大きめの行列だとCuPyに軍配が上がります.

s1 = time.time()
a = np.ones((1000, 1000),dtype=np.float32)
a.dot(a.T)

s2 = time.time()
b = cp.ones((1000, 1000),dtype=cp.float32)
b.dot(b.T)

s3 = time.time()
c = chainer.cuda.to_gpu(cp.ones((1000, 1000),dtype=cp.float32))
c.dot(c.T)

s4 = time.time()

print 'np:',s2-s1
print 'cp:',s3-s2
print 'cp2:',s4-s3
np: 0.0469000339508
cp: 0.281046152115
cp2: 0.000430822372437

※とある事情でコードを手打ちで書いたのでミスがあるかもしれません,悪しからず.

負の数の引き算ってなんだっけ

こんにちは.

先日研究室で数学ってよくわからないという話をしていまして, その中に負の数の引き算ってなんだっけという話題になりました.

おそらく大多数の人が以下のように頭の中で変換して計算していると思います.

{ \displaystyle
a - (-b) = a + b
}

この変換式を使えば高校入試や大学入試の数学の問題は解けるので, これまで生きてきて問題はなかったのですが, もし負の数に初めて出会った小学生や中学生から

「負の数の引き算ってなに?」

と聞かれてもうまく答えられる自信がありません.

今回の記事では, 小学生や中学生に負の数の引き算を説明できる大人になれることを目指して, 自分なりの解釈を考えてみようと思います.

正の数の加減算の例え話

幼稚園児や小学生に加減算の説明をする場合, 実際のモノを使って例え話をするのがオーソドックスな教え方だと思います.

足し算の例

たかしくんの家の冷蔵庫にじゃがいもが2個入っています. たかしくんは学校の帰り道にじゃがいも畑に寄り道をして, そこから3個じゃがいもをくすねて家の冷蔵庫に入れました. 冷蔵庫に入っているじゃがいもの数はいくつでしょう.

{ \displaystyle
2 + 3 = 5
}

引き算の例

たかしくんの家の冷蔵庫にじゃがいもが5個入っています. たかしくんは友達の家に遊びに行くとき, 手土産としてじゃがいもを4個持っていきました. 冷蔵庫に残っているじゃがいもの数はいくつでしょう.

{ \displaystyle
5 - 4 = 1
}

たかしくんのクレイジーな行動が気になりますが, このような例題を使って教えることができます.

しかし,負の数が絡んでくると例えるのが難しくなります. じゃがいもを1個2個と数えることができても,-1個-2個と数えることはできないからです.

提案手法

モノを負の数で表現するのは難しいので, モノに対する行動を正の数・負の数で表現して, 行動したことによる結果を足し算や引き算で表現します.

じゃがいもの例だと以下のように定義します.

  • 正の数:じゃがいもを冷蔵庫に入れるという行動
  • 負の数:じゃがいもを冷蔵庫から出すという行動
  • 足し算:行動した後の状態を求める演算子
  • 引き算:行動する前の状態を求める演算子

負の数の足し算の例

たかしくんの家の冷蔵庫にじゃがいもが5個入っています. たかしくんは友達の家に遊びに行くとき, 手土産としてじゃがいもを4個持っていきました. 冷蔵庫に残っているじゃがいもの数はいくつでしょう.

  • じゃがいもを冷蔵庫から4個出すという行動:-4
  • 行動した後の状態を求めたい:+

{ \displaystyle
5 + (- 4) = 1
}

負の数の引き算の例

たかしくんは友達の家に遊びに行くとき, 手土産としてじゃがいもを4個持っていきました. 冷蔵庫に残っているじゃがいもは1個でした. 元々冷蔵庫にじゃがいもはいくつだったでしょうか.

  • じゃがいもを冷蔵庫から4個出すという行動:-4
  • 行動する前の状態を求めたい:-

{ \displaystyle
1 - (- 4) = 5
}

Caffe2を使ってみたその1「インストール」

こんにちは.

Caffe2というDeep Learning用のフレームワークが出たようです. まだドキュメントをちゃんと読んでいないのでその良し悪しはわかりませんがとりあえず試してみることとします.

caffe2.ai

環境

項目 詳細
OS Ubuntu 14.04
GPU GTX970

ちなみに2じゃないほうのCaffeをインストール済みです.

手順

手順といっても,Caffe2の公式ドキュメントの方法に従うだけです. ソースからのビルドを試してみます.

Install | Caffe2

依存パッケージのインストール

# 私の場合Caffeを入れたときに以下のパッケージは導入済みなので飛ばしました
$ sudo apt-get update
$ sudo apt-get install -y --no-install-recommends build-essential cmake git libgoogle-glog-dev libprotobuf-dev protobuf-compiler python-dev python-pip
$ sudo pip install numpy protobuf

CUDAとcuDNNのインストール

# 公式ドキュメントにはグラフィックドライバーを更新してねと書いていました.
# そのあたりは各自で適宜行って下さい.

# 当初CUDA7.5を導入済みだったのでここを飛ばしましたが,後述のエラーが出ました.8.0が良いのでしょうか.
$ sudo apt-get update && sudo apt-get install wget -y --no-install-recommends
$ wget "http://developer.download.nvidia.com/compute/cuda/repos/ubuntu1404/x86_64/cuda-repo-ubuntu1404_8.0.61-1_amd64.deb"
$ sudo dpkg -i cuda-repo-ubuntu1404_8.0.61-1_amd64.deb
$ sudo apt-get update
$ sudo apt-get install cuda

$ CUDNN_URL="http://developer.download.nvidia.com/compute/redist/cudnn/v5.1/cudnn-8.0-linux-x64-v5.1.tgz"
$ wget ${CUDNN_URL}
$ sudo tar -xzf cudnn-8.0-linux-x64-v5.1.tgz -C /usr/local
$ rm cudnn-8.0-linux-x64-v5.1.tgz && sudo ldconfig

残りの依存パッケージのインストール

$ sudo apt-get install -y --no-install-recommends libgflags2
$ sudo apt-get install -y --no-install-recommends libgtest-dev libiomp-dev libleveldb-dev liblmdb-dev libopencv-dev libopenmpi-dev libsnappy-dev openmpi-bin openmpi-doc python-pydot
$ sudo pip install flask graphviz hypothesis jupyter matplotlib pydot python-nvd3 pyyaml requests scikit-image scipy setuptools tornado

ソースのクローンとビルド

# ホームディレクトリにクローンしました.場所については適宜読み替えて行って下さい.
# makeでエラーが出たらmake cleanしてやり直し
$ git clone --recursive https://github.com/caffe2/caffe2.git && cd caffe2
$ make && cd build && sudo make install
$ python -c 'from caffe2.python import core' 2>/dev/null && echo "Success" || echo "Failure"

環境変数の設定

「.bashrc」の末尾にパスを追記します.

$ gedit ~/.bashrc &
# .bashrcの末尾に追記
# 2行目のパスは各自読み替えて下さい.
export PYTHONPATH=/usr/local:$PYTHONPATH
export PYTHONPATH=$PYTHONPATH:/home/username/caffe2/build
export LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH

動作確認

動くかな? ワクワク……

$ python -m caffe2.python.operator_test.relu_op_test
Trying example: test_relu(self=<__main__.TestRelu testMethod=test_relu>, X=array([[ 1.        ,  0.58414382, -0.07458938],
       [-0.92077535,  1.        , -0.31444678]], dtype=float32), gc=device_type: 1, dc=[, device_type: 1], engine=u'CUDNN')
Trying example: test_relu(self=<__main__.TestRelu testMethod=test_relu>, X=array([-0.        , -0.77440119], dtype=float32), gc=, dc=[, device_type: 1], engine=u'')
Trying example: test_relu(self=<__main__.TestRelu testMethod=test_relu>, X=array([ 0.,  0.], dtype=float32), gc=, dc=[, device_type: 1], engine=u'')
Trying example: test_relu(self=<__main__.TestRelu testMethod=test_relu>, X=array([[[ 0.12101772,  1.        ,  0.98191798, -0.75570065],
        [ 0.        ,  1.        , -0.66422468, -0.87821025],
        [-0.76647252,  0.19047344, -0.32112685, -0.        ],
        [ 0.6859479 , -0.47230539, -0.79940522, -0.24955569]],

       [[ 1.        , -0.36730164, -0.78970796,  0.46469435],
        [-0.95587206, -0.44132483,  0.        , -0.28097823],
        [-0.08904378,  0.38005501, -0.61275059,  0.79579282],
        [-0.02774031,  0.50639385, -0.91766995, -0.33312017]]], dtype=float32), gc=device_type: 1, dc=[, device_type: 1], engine=u'CUDNN')
Trying example: test_relu(self=<__main__.TestRelu testMethod=test_relu>, X=array([[-0.56960249, -0.84849566, -0.        ]], dtype=float32), gc=, dc=[, device_type: 1], engine=u'CUDNN')
Trying example: test_relu(self=<__main__.TestRelu testMethod=test_relu>, X=array([ -0.00000000e+00,  -6.69241369e-01,   3.31036976e-28], dtype=float32), gc=device_type: 1, dc=[, device_type: 1], engine=u'CUDNN')
Trying example: test_relu(self=<__main__.TestRelu testMethod=test_relu>, X=array([ 0.97428375, -0.07135547], dtype=float32), gc=device_type: 1, dc=[, device_type: 1], engine=u'')
Trying example: test_relu(self=<__main__.TestRelu testMethod=test_relu>, X=array([-0., -0.], dtype=float32), gc=device_type: 1, dc=[, device_type: 1], engine=u'')
Trying example: test_relu(self=<__main__.TestRelu testMethod=test_relu>, X=array([-0.        , -0.94964397], dtype=float32), gc=device_type: 1, dc=[, device_type: 1], engine=u'CUDNN')
Trying example: test_relu(self=<__main__.TestRelu testMethod=test_relu>, X=array([ 0.41938838,  0.64380383, -0.30215767], dtype=float32), gc=device_type: 1, dc=[, device_type: 1], engine=u'')
.
----------------------------------------------------------------------
Ran 1 test in 0.946s

OK

OKらしいです.

エラーの対処

make中に以下のエラーに遭遇しました

[ 59%] Built target Caffe2_CPU
make[3]: ディレクトリ `/home/username/caffe2/build' に入ります
[ 59%] Building NVCC (Device) object caffe2/CMakeFiles/Caffe2_GPU.dir/utils/./Caffe2_GPU_generated_math_gpu.cu.o
/home/username/caffe2/caffe2/utils/conversions.h(137): warning: variable "r" was declared but never referenced

/home/username/caffe2/caffe2/utils/math_gpu.cu(136): error: identifier "CUDA_R_16F" is undefined

/home/username/caffe2/caffe2/utils/math_gpu.cu(312): error: identifier "CUDA_R_16F" is undefined

/home/username/caffe2/caffe2/utils/math_gpu.cu(496): error: identifier "CUDA_R_16F" is undefined

/home/username/caffe2/caffe2/utils/math_gpu.cu(496): error: identifier "CUDA_R_32F" is undefined

/home/username/caffe2/caffe2/utils/math_gpu.cu(496): error: identifier "cublasDotEx" is undefined

/home/username/caffe2/caffe2/utils/math_gpu.cu(740): error: identifier "CUDA_R_16F" is undefined

/home/username/caffe2/caffe2/utils/math_gpu.cu(740): error: identifier "CUDA_R_32F" is undefined

/home/username/caffe2/caffe2/utils/math_gpu.cu(740): error: identifier "cublasAxpyEx" is undefined

8 errors detected in the compilation of "/tmp/tmpxft_000079b6_00000000-7_math_gpu.cpp1.ii".
CMake Error at Caffe2_GPU_generated_math_gpu.cu.o.cmake:260 (message):
  Error generating file
  /home/username/caffe2/build/caffe2/CMakeFiles/Caffe2_GPU.dir/utils/./Caffe2_GPU_generated_math_gpu.cu.o


make[3]: *** [caffe2/CMakeFiles/Caffe2_GPU.dir/utils/./Caffe2_GPU_generated_math_gpu.cu.o] エラー 1
make[3]: ディレクトリ `/home/username/caffe2/build' から出ます
make[2]: *** [caffe2/CMakeFiles/Caffe2_GPU.dir/all] エラー 2
make[2]: ディレクトリ `/home/username/caffe2/build' から出ます
make[1]: *** [all] エラー 2
make[1]: ディレクトリ `/home/username/caffe2/build' から出ます
make: *** [all] エラー 2

CUDA周りのエラーですかね? CUDAを入れ直してから「.bashrc」の末尾にパスを追加してやりました.

$ gedit ~/.bashrc &
# .bashrcの末尾に追記
export PATH=/usr/local/cuda-8.0/bin:${PATH}
export LD_LIBRARY_PATH=/usr/local/cuda-8.0/lib64:${LD_LIBRARY_PATH}

再起動してから再びmakeをするとうまく行きました.

ガンダムエクシアダークマター3 つや消し

こんにちは.

すっかり報告を忘れていたエクシアダークマターの組み立て記録です. 今回は初めてつや消しに挑戦をしてみました. つや消しには「Mr.トップコートつや消し」を使いました.

Amazon | Mr.トップコートスプレー つや消し B503 | 溶剤・うすめ液 通販

パーツのマスキング

スプレーの粒子がかからない部分が出ないようにパーツをある程度分解します. また,パーツの接合部やクリアパーツなどつや消しをしたくない部分にはマスキングテープを張っておきます.

f:id:ytbilly3636:20170409125306j:plain

エクシアの関節部分のマスキングがめんどくさかったです.

f:id:ytbilly3636:20170409125400j:plain

ちなみにに明るい色のパーツにはスミ入れもしています.

f:id:ytbilly3636:20170409125722j:plain

スプレー吹きかけ

各パーツをクリップで留めてムラ無くスプレーを吹きかけます. ベースはダンボールを切リ貼りして手作りしたものです.

f:id:ytbilly3636:20170409125846j:plain

1日乾かしたらツヤが消えてマット感が出ていました. 写真ではわかりづらいと思いますが, スプレーを吹きかけた部分はすりガラスのような質感になり, マスキングをしていたクリアパーツはツルツルのままで仕上げることが出来ました.

f:id:ytbilly3636:20170409130130j:plain

またクリップのツヤも消えていました. 写真の右側がつや消しスプレーを吹きかけたクリップです. メタリックなパーツにはつや消しスプレーを吹きかけないほうが良いかもしれません.

f:id:ytbilly3636:20170409130459j:plain