2024年3月12日 更新

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

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

40,135 view お気に入り 2
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って面白い!!」へ!
Extracting Straight Lines〜画像から境界線を効率よく求める方法〜

Extracting Straight Lines〜画像から境界線を効率よく求める方法〜

本記事では,IEEE Transactions on Pattern Analysis and Machine Intelligence に投稿された,「Extracting Straight Lines」の論文を説明し,実装を行います.1986年に投稿された少し古めの論文ですが,アイディアは非常に面白いです.
ディジタル画像処理~pythonによる空間フィルタリングpart1~ 

ディジタル画像処理~pythonによる空間フィルタリングpart1~ 

ディジタル画像処理を解説します.今回は,代表的な空間フィルタリングをpythonで実行してみました。
亀谷 桃子 | 13,491 view
Morphology (モルフォロジー) 変換の実装 ~ Python + OpenCV ~

Morphology (モルフォロジー) 変換の実装 ~ Python + OpenCV ~

画像処理の一つ,モルフォロジー変換をPython と OpenCVのライブラリを用いて実装し,それを2値画像に対して適用します.
Julia と画像処理②〜画像のセグメンテーション(Seed Region Growing とFelzenszwalbアルゴリズム)〜

Julia と画像処理②〜画像のセグメンテーション(Seed Region Growing とFelzenszwalbアルゴリズム)〜

プログラミング言語「julia」を用いて画像処理を行います.インストールに続き,今回は画像のセグメンテーションのライブラリを用いて,セグメンテーションを行います.

この記事のキーワード

この記事のキュレーター

Mochizuki Mochizuki