2017年2月23日 更新

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

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

10,122 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)
    files.sort()
    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"

import sys
import os.path
import shutil
import glob
import random

# 書き込むテキストファイル
train_list = open("train.txt", "w")
test_list = open("test.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")]
    startcount = count
    length = len(images)
    for image in images:
        # 各クラスのデータの75%を学習に25%をテストに使う
        if random.random() < 0.75:
            train_list.write(imagefolder+image+" %d\n" %classno)
        else:
            test_list.write(imagefolder+image+" %d\n" %classno)
        count+=1
    classno+=1

train_list.close()
test_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/0/0.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.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 件

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

ImageJインストール(Mac)#ImageJの初心者から中級者まで#

ImageJインストール(Mac)#ImageJの初心者から中級者まで#

ImageJのインストールの仕方についてまとめました! 「ImageJってなに?」から「ImageJって面白い!!」へ!
三好 裕之 | 3,476 view
Pythonで画像処理② Data Augmentation (画像の水増し)

Pythonで画像処理② Data Augmentation (画像の水増し)

画像の水増し、Data Augmentationと呼ばれる方法になりますが、学習に使う画像に変形を加えたり、ノイズを加えたり、明るさを変えたりといった処理を行う方法を紹介します。学習画像に様々な処理を行うことで認識がロバストになるというメリットがあります。
望月 優輝 | 1,713 view
LPixel主催!「画像解析ハッカソン」イベントまとめ

LPixel主催!「画像解析ハッカソン」イベントまとめ

2017年7月26日に行われた「ライフサイエンス画像解析カジュアルハッカソン!」(https://goo.gl/9mjwfc)のまとめ記事です.
井上 大輝 | 629 view
点像分布関数の話

点像分布関数の話

光学系を理解するうえで前提として知っておいた方が良い内容
Yoshiyuki Arai | 354 view
現役JDと学ぶ画像処理入門①〜openCV入門〜

現役JDと学ぶ画像処理入門①〜openCV入門〜

openCV入門(画像の読み込み、表示、保存、線形変換、拡大縮小)
広部ゆりか | 10,079 view

この記事のキーワード

この記事のキュレーター

望月 優輝 望月 優輝