[PYTHON] Schätzung von Krebspatienten anhand von CT-Bildern mittels CNTK

Gliederung

Es wird ein Bereich sein, in dem Ergebnisse aus einem frühen Stadium im Bereich des tiefen Lernens erzielt wurden. Ob Sie Krebs haben oder nicht, kann einfach als maschinelles Lernen modelliert werden, indem die Eingabedaten in zwei Teile unterteilt werden. Mit einer bestimmten Datenmenge ist es möglich, ein Modell von Grund auf neu zu erstellen und zu verwenden. Dieses Mal möchte ich jedoch eine Methode zur Verwendung eines allgemeinen ImageNet-Bilderkennungsmodells für das Transferlernen vorstellen. Ursprünglich aus dem Folgenden wurde ich gefragt, wie es in Azure ML ausgeführt werden soll, da es in der Cortana Ingelligence-Galerie vorhanden ist. Aus einer solchen Situation möchte ich zunächst anhand dieses Inhalts erklären. https://gallery.cortanaintelligence.com/Notebook/Medical-Image-Recognition-for-the-Kaggle-Data-Science-Bowl-2017-with-CNTK-and-LightGBM-1

Es gibt eine Community-Site für Datenwissenschaftler namens Kaggle, auf der der Data Science Bowl 2017 in einem Wettbewerb stattfand. Eines der dort bereitgestellten Themen war die Krebserkennung anhand von CT-Bildern. Im Wettbewerb werden ungefähr 1500 tatsächliche CT-Daten bereitgestellt, und die Analyselogik wird von dort aus konkurriert. Derzeit (Stand März 2017) liegt die höchste Erkennungsrate bei über 99%. https://www.kaggle.com/c/data-science-bowl-2017

Methode

Für eine genaue Analyse ist eine 3D-Faltung erforderlich, die für 2D-Bilder etwas überwältigend ist, jedoch das trainierte ImageNet-Modell verwendet. Der Umriss dieses Prozesses ist in der Abbildung dargestellt.

zu.png

Das LightBGM-Training dauert nur wenige Sekunden, daher wird die Funktion meistens mithilfe des ResNet-Modells extrahiert.

Vorbereitungen

-Einführung von CNTK Siehe unten. Ich benutze CNTK2.0RC1. https://analyticsai.wordpress.com/2017/04/04/cntk2-0b15%e3%82%a4%e3%83%b3%e3%82%b9%e3%83%88%e3%83%bc%e3%83%ab/

-Daten Herunterladen von Kaggle. Aufgrund seiner Größe dauert es lange. https://www.kaggle.com/c/data-science-bowl-2017/data

-Python CNTK arbeitet normalerweise in der Anaconda-Umgebung. Führen Sie pydicom ein, um CT-Bilder zu lesen. Es kann mit pip installiert werden. pip install pydicom

-LightGBM Klicken Sie hier zur Installation https://analyticsai.wordpress.com/2017/04/04/lightgbm/

-PreTrained Modell Da es sich um Transferlernen handelt, ist ein ImageNet-Modell erforderlich. CNTK ist in verschiedenen trainierten Modellen erhältlich und steht frei zum Download zur Verfügung. https://www.microsoft.com/en-us/research/product/cognitive-toolkit/model-gallery/

Laden Sie das ResNet 152-Modell von diesem herunter. (Dies scheint eine Konvertierung von Caffes Modell zu sein). https://github.com/Microsoft/CNTK/tree/master/Examples/Image/Classification/ResNet#cntk-examples-imageclassificationresnet

Der Originalartikel scheint hier heruntergeladen zu sein. https://migonzastorage.blob.core.windows.net/deep-learning/models/cntk/imagenet/ResNet_152.model

Ordnerstruktur

\ data \ stage1 \ - CT-Scandaten \ anxtures \ features0001 - Aus Scandaten berechnete Funktionswerte Sie müssen im Voraus einen Ordner erstellen.

ResNet_152.model wird im Ordner unter dem Modell gespeichert. \ local \ models - Speichert ResNet-Modelldateien

Arbeit

Extrahieren Sie die heruntergeladenen CT-Bilddaten in den Ordner unter stage1. Der ursprüngliche Python-Code funktioniert nicht so wie er ist. Ändern Sie ihn daher unten. Um ehrlich zu sein, habe ich es verschoben, während ich verschiedene Korrekturen vorgenommen habe. Da CNTK zu RC wird, hat sich der Wert der Ebene in der Mitte von numpy.array in python list geändert. Dieser Teil wirkt sich auf den Transfer-Lerncode aus und muss geändert werden. Mit diesem Artikel können Sie abschätzen, wer Krebs hat, aber Sie wissen nicht, wo Krebs ist. Beim maschinellen Lernen besteht der Zweck darin, vorherzusagen: "Warum passiert das?" In den meisten Fällen kann ich die Frage nicht beantworten. Es ist notwendig, eine andere Methode in Betracht zu ziehen, um den Standort zu schätzen. Ich möchte diesen Teil das nächste Mal schreiben. Der Code ist unten angehängt. Dies ist eine modifizierte Version des Codes auf der obigen Site.

#Load libraries
 import sys,os
 import numpy as np
 import dicom
 import glob
 from cntk.device import set_default_device, gpu
 from matplotlib import pyplot as plt
 import cv2
 import pandas as pd
 import time
 from sklearn import cross_validation
 from cntk import load_model
 from cntk.ops import combine
 from cntk.io import MinibatchSource, ImageDeserializer, StreamDef, StreamDefs
 from lightgbm.sklearn import LGBMRegressor

print("System version:", sys.version, "\n")
 #print("CNTK version:",pkg_resources.get_distribution("cntk").version)
 #Put here the number of your experiment
 EXPERIMENT_NUMBER = '0001'

#Put here the path to the downloaded ResNet model
 MODEL_PATH='/local/models/ResNet_152.model'

#Put here the path where you downloaded all kaggle data
 DATA_PATH='/'

# Path and variables
 STAGE1_LABELS=DATA_PATH + 'stage1_labels.csv'
 STAGE1_SAMPLE_SUBMISSION=DATA_PATH + 'stage1_sample_submission.csv'
 STAGE1_FOLDER=DATA_PATH + 'stage1/'
 FEATURE_FOLDER=DATA_PATH + 'features/features' + EXPERIMENT_NUMBER + '/'
 SUBMIT_OUTPUT='submit' + EXPERIMENT_NUMBER + '.csv'
 # Timer class
 class Timer(object):
 def __enter__(self):
 self.start()
 return self

def __exit__(self, *args):
 self.stop()

def start(self):
 self.start = time.clock()

def stop(self):
 self.end = time.clock()
 self.interval = self.end - self.start

def get_3d_data(path):
 slices = [dicom.read_file(path + '/' + s) for s in os.listdir(path)]
 slices.sort(key=lambda x: int(x.InstanceNumber))
 return np.stack([s.pixel_array for s in slices])
 def get_data_id(path, plot_data=False):
 sample_image = get_3d_data(path)
 sample_image[sample_image == -2000] = 0
 if plot_data:
 f, plots = plt.subplots(4, 5, sharex='col', sharey='row', figsize=(10, 8))

batch = []
 cnt = 0
 dx = 40
 ds = 512
 for i in range(0, sample_image.shape[0] - 3, 3):
 tmp = []
 for j in range(3):
 img = sample_image[i + j]
 img = 255.0 / np.amax(img) * img
 img = cv2.equalizeHist(img.astype(np.uint8))
 img = img[dx: ds - dx, dx: ds - dx]
 img = cv2.resize(img, (224, 224))
 tmp.append(img)

tmp = np.array(tmp)
 batch.append(np.array(tmp))

if plot_data:
 if cnt < 20:
 plots[cnt // 5, cnt % 5].axis('off')
 plots[cnt // 5, cnt % 5].imshow(tmp[0,:,:], cmap='gray')
 cnt += 1

if plot_data: plt.show()

batch = np.array(batch, dtype='int')
 return batch
 def get_extractor():
 node_name = "z.x"
 loaded_model  = load_model(MODEL_PATH)
 node_in_graph = loaded_model.find_by_name(node_name)
 output_nodes  = combine([node_in_graph.owner])
 return output_nodes

def calc_features(verbose=False):
 net = get_extractor()
 for folder in glob.glob(STAGE1_FOLDER+'*'):
 foldername = os.path.basename(folder)
 if os.path.isfile(FEATURE_FOLDER+foldername+'.npy'):
 if verbose: print("Features in %s already computed" % (FEATURE_FOLDER+foldername))
 continue
 batch = get_data_id(folder)
 if verbose:
 print("Batch size:")
 print(batch.shape)
 feats = np.array(net.eval(batch))
 if verbose:
 print(feats.shape)
 print("Saving features in %s" % (FEATURE_FOLDER+foldername))
 np.save(FEATURE_FOLDER+foldername, feats)

def train_lightgbm():
 df = pd.read_csv(STAGE1_LABELS)

x = np.array([np.mean(np.load(FEATURE_FOLDER+'%s.npy' % str(id)), axis=1).flatten() for id in df['id'].tolist()] )
 y = df['cancer'].as_matrix()
 print(x.shape)

trn_x, val_x, trn_y, val_y = cross_validation.train_test_split(x, y, random_state=42, stratify=y,
 test_size=0.20)
 clf = LGBMRegressor(max_depth=50,
 num_leaves=21,
 n_estimators=5000,
 min_child_weight=1,
 learning_rate=0.001,
 nthread=24,
 subsample=0.80,
 colsample_bytree=0.80,
 seed=42)
 clf.fit(trn_x, trn_y, eval_set=[(val_x, val_y)], verbose=True, eval_metric='l2', early_stopping_rounds=300)
 return clf

def compute_training(verbose=True):
 with Timer() as t:
 clf = train_lightgbm()
 if verbose: print("Training took %.03f sec.\n" % t.interval)
 return clf

def compute_prediction(clf, verbose=True):
 df = pd.read_csv(STAGE1_SAMPLE_SUBMISSION)
 x = np.array([np.mean(np.load((FEATURE_FOLDER+'%s.npy') % str(id)), axis=1).flatten() for id in df['id'].tolist()])

with Timer() as t:
 pred = clf.predict(x)
 if verbose: print("Prediction took %.03f sec.\n" % t.interval)
 df['cancer'] = pred
 return df

def save_results(df):
 df.to_csv(SUBMIT_OUTPUT, index=False)
 calc_features(verbose=True)

clf = compute_training(verbose=True)

df = compute_prediction(clf)
 print("Results:")
 df.head()

save_results(df)

Das Ergebnis wird in eine Datei ausgegeben. Teil der Ausgabedatei.

id,cancer
026470d51482c93efc18b9803159c960,0.40692197700808486
031b7ec4fe96a3b035a8196264a8c8c3,0.3037382335250943
03bd22ed5858039af223c04993e9eb22,0.2324142770435242
06a90409e4fcea3e634748b967993531,0.20775132462023793
07b1defcfae5873ee1f03c90255eb170,0.3054943422884507
0b20184e0cd497028bdd155d9fb42dc9,0.21613283326493204
12db1ea8336eafaf7f9e3eda2b4e4fef,0.2073817116259871
159bc8821a2dc39a1e770cb3559e098d,0.28326504404734154
174c5f7c33ca31443208ef873b9477e5,0.23168542729470515
1753250dab5fc81bab8280df13309733,0.21749273848859857
1cf8e778167d20bf769669b4be96592b,0.18329884419207843
1e62be2c3b6430b78ce31a8f023531ac,0.3276063617078295
1f6333bc3599f683403d6f0884aefe00,0.2092160345076576
1fdbc07019192de4a114e090389c8330,0.2276893908994118
2004b3f761c3f5dffb02204f1247b211,0.20776188822078875

Zum Beispiel hat eine Person mit der ID 2703df8c469906a06a45c0d7ff501199 eine Wahrscheinlichkeit von 0,5561665263809848, sodass man sagen kann, dass sie ziemlich verdächtig ist.

Recommended Posts

Schätzung von Krebspatienten anhand von CT-Bildern mittels CNTK
Holen Sie sich Bilder per Stichwortsuche von Twitter