2016年12月12日 更新

細胞種を機械学習で判別する!

今回は深層学習、ディープラーニングで細胞の種類を判別してみたいと思っています。判別するのは私が普段実験で使っている上皮細胞のEpH4という細胞と、遺伝子発現用のHEK293という細胞です。

1,268 view お気に入り 0
import cv2
import numpy as np

def rotateImage(image, angle):
    center = tuple(np.array(image.shape)[:2]/2) # 2d !
    rot_mat = cv2.getRotationMatrix2D(center,angle,1.0)
    result = cv2.warpAffine(image, rot_mat, tuple(np.array(image.shape)[:2]) ,flags=cv2.INTER_LINEAR)
    return result

def rotateImageAndSave(path, label):
    files = glob.glob(path)
    for i, filename in enumerate(files):
        print i,
        img = cv2.imread(filename, cv2.IMREAD_GRAYSCALE)
        for deg in range(90,360,90):
            img = rotateImage(img, deg)
            str_deg = str(deg)
            output = "../train_data/"+label+"/"+str(i)+"rotate"+str_deg+'.png'
            cv2.imwrite(output, img)
            flipX = cv2.flip(img, 0)
            output = "../train_data/"+label+"/"+str(i)+"rotate"+str_deg+"flipX"+'.png'
            cv2.imwrite(output, flipX)
            flipY = cv2.flip(img, 1)
            output = "../train_data/"+label+"/"+str(i)+"rotate"+str_deg+"flipY"+'.png'
            cv2.imwrite(output, flipY)
            flipXY = cv2.flip(img, -1)
            output = "../train_data/"+label+"/"+str(i)+"rotate"+str_deg+"flipXY"+'.png'
            cv2.imwrite(output, flipXY)
水増し関数.py
rotateImageAndSave(r"../train_data/1/*.png","1")
rotateImageAndSave(r"../train_data/0/*.png","0")
水増し.py

画像パスとラベルの対応関係を記述する

inputfolder = r"../train_data"
outputfolder = r"../train_data/index"
outputfolderimgname = "i"  # 出力画像フォルダ名

import sys
import os.path
import shutil
import glob

param = sys.argv

labels = os.listdir(inputfolder)

if os.path.isdir(outputfolder) != True:
    os.mkdir(outputfolder)
if os.path.isdir(outputfolder+"/"+outputfolderimgname) != True:
    os.mkdir(outputfolder+"/"+outputfolderimgname)

# 書き込むテキストファイル
train_list = open(outputfolder+"/train.txt", "w")
test_list = open(outputfolder+"/test.txt", "w")
label_list = open(outputfolder+"/label.txt", "w")

classno = 0
count = 0
for label in range(0,2):
    label=str(label)
    imagefolder = inputfolder+"/"+label+"/"

    images = [r.split('/')[-1] for r in glob.glob(imagefolder+"*.png")]
    #print images
    label_list.write(label+"\n")
    startcount = count
    length = len(images)
    for image in images:
        outimagepath = outputfolder+"/"+outputfolderimgname+"/image%07d" %count+".png"
        shutil.copy(imagefolder+image, outimagepath)
        # 各クラスのデータの75%を学習に25%をテストに使う
        if count-startcount < length*0.75:
            train_list.write(outimagepath+" %d\n" %classno)
        else:
            test_list.write(outimagepath+" %d\n" %classno)
        count+=1
    classno+=1

train_list.close()
test_list.close()
label_list.close()
print "Complete!"
ラベル対応.py

学習モデル

from chainer import cuda, Function, FunctionSet, gradient_check, Variable, optimizers, serializers
from chainer.training import extensions
import chainer.functions as F

class CNN():
    #cuda.get_device(0).use()    # GPU用コード
    def __init__(self):
        self.model = FunctionSet(
            conv1 = F.Convolution2D(1,32,3,pad=1),
            conv2 = F.Convolution2D(32,32,3,pad=1),
            conv3 = F.Convolution2D(32,16,3,pad=1),
            conv4 = F.Convolution2D(16,16,3,pad=1),
            l1 = F.Linear(256,50),#1つ目の値は計算方法があるが適当でもChainerが実行時に正しい値を教えてくれる
            l2 = F.Linear(50,3),
        ).to_cpu()
            

    def forward(self, x_data, y_data, train=True):
        x, t = Variable(x_data), Variable(y_data)
        c = F.max_pooling_2d(F.relu(self.model.conv1(x)), 2)
        c = F.max_pooling_2d(F.relu(self.model.conv2(c)), 2)
        c = F.max_pooling_2d(F.relu(self.model.conv3(c)), 2)
        c = F.max_pooling_2d(F.relu(self.model.conv4(c)), 2)
        h = F.dropout(F.relu(self.model.l1(c)), train=train)
        y = self.model.l2(h)

        if train:   # 学習時
            return F.softmax_cross_entropy(y, t)
        else:
            return y       # 評価時
モデル.py

いよいよ学習!

学習の前に元データの画像サイズを確認しておきます。
今回は64と出力されました。1片64の正方形画像です。
import cv2
img = cv2.imread(r"../train_data/index/i/image0000000.png", 0)
print img.shape
imagesize = img.shape[0]
画像サイズ.py
学習のためのコードです。今回は100回学習を繰り返します。
import numpy as np
import chainer
from chainer import Function, FunctionSet, gradient_check, Variable, optimizers, serializers
from chainer.training import extensions
import argparse
import random
import chainer.functions as F
import cv2
import time

#cuda.get_device(0).use()    # GPU用コード

# 学習モデル設定
model = CNN()
optimizer = optimizers.Adam()
optimizer.setup(model.model)

# 学習データリストファイルから一行ずつ読み込む
train_list = []
for line in open(r"../train_data/index/train.txt"):
    pair = line.strip().split()
    train_list.append((pair[0], np.float32(pair[1])))

# 画像データとラベルデータを取得する
x_train = []    # 画像データ格納
y_train = []    # ラベルデータ格納
for filepath, label in train_list:
    img = cv2.imread(filepath, 0)   # グレースケールで読み込む
    x_train.append(img)
    y_train.append(label)

# 学習で使用するsoftmax_cross_entropyは
# 学習データはfloat32,ラベルはint32にする必要がある。
x_train = np.array(x_train).astype(np.float32)
y_train = np.array(y_train).astype(np.int32)
# 画像を(学習枚数、チャンネル数、高さ、幅)の4次元に変換する
x_train = x_train.reshape(len(x_train), 1, imagesize, imagesize) / 255

N = len(y_train)

batchsize = 60
datasize = len(x_train)
n_epoch =  100   # 繰り返し学習回数
# 学習開始
train_start = time.time()

print "start"
for epoch in range(1, n_epoch+1):
    sum_loss = 0
    perm = np.random.permutation(N) # データセットの順番をシャッフル
    train_start_one = time.time()
    for i in range(0,datasize, batchsize):
        x_batch = x_train[perm[i:i+batchsize]] # バッチサイズ分のデータを取り出す
        y_batch = y_train[perm[i:i+batchsize]]
        # 初期化
        optimizer.zero_grads()
        # 誤差伝播
        loss = model.forward(x_batch, y_batch, train=True)
        # 誤差逆伝播
        loss.backward()
        # ネットワークパラメータ更新
        optimizer.update()

        sum_loss += loss.data
    print "epoch:{} loss={} time:{}".format(epoch, sum_loss / (datasize/batchsize), time.time()-train_start_one)
    if epoch%10==0:
        serializers.save_npz("model_{}".format(n_epoch), model.model)
        serializers.save_npz("state_{}".format(n_epoch), optimizer)
        
print "train time:{}".format(time.time()-train_start)
# 学習したモデルを出力する
serializers.save_npz("model_{}".format(n_epoch), model.model)
serializers.save_npz("state_{}".format(n_epoch), optimizer)
学習.py

学習完了!

学習過程

学習過程

私のMacbook Air ではtrain time:1088.80467081とでました。約15分くらいですね。続いて精度の検証を行ってみたいと思います。
48 件

関連する記事 こんな記事も人気です♪

Deep learningで画像認識④〜畳み込みニューラルネットワークの構成〜

Deep learningで画像認識④〜畳み込みニューラルネットワークの構成〜

畳み込みニューラルネットワークは、画像データに特化した特徴量の抽出と分類が可能です。今回は、畳み込みニューラルネットワークの構成についての内容です。
木田智士 | 426 view
OpenCVでライフサイエンスを加速する!

OpenCVでライフサイエンスを加速する!

OpenCVはそもそもはコンピュータービジョン向けのライブラリです。それゆえ、顔認識や文字認識、カメラキャリブレーションなど、いわゆるロボットや自動運転車などの工学系の応用を主に想定して開発されていますが、ライフサイエンスの分野でもOpenCVは非常に役に立つツールです。
望月 優輝 | 430 view
OpenCVで重心を計算する

OpenCVで重心を計算する

重心を計算する方法の紹介です
望月 優輝 | 494 view
LSTMとは〜概要と応用について〜

LSTMとは〜概要と応用について〜

音声信号処理や文章・対話の生成に用いられているLSTM(Long Short Term Memory)についてまとめました。
三好 裕之 | 529 view
pythonによるtensorflow〜deepdreamによる画像変換〜

pythonによるtensorflow〜deepdreamによる画像変換〜

今回は前回のtensorflowの記事に引き続き、deepdreamによる画像変換についてご紹介します。
三好 裕之 | 495 view

この記事のキーワード

この記事のキュレーター

望月 優輝 望月 優輝