
在一般的圖形識別中,Google 資料集的 MNIST 是很好的資料。而在醫學影像識別中也有很多的影像圖片。這裡將醫學中常見的六種影像:腹部電腦斷層、胸腔磁共振造影、胸部電腦斷層、胸部 X 光、手部 X 光及頭部 X 光集合起來來做影像辨識(classification)的工作。本文紀錄處理圖片資料的預先處裡流程,最後結合深度學習框架Tensorflow 及 keras 完成深度學習中的分類(classification)工作。
1. 資料放置位置與記憶體空間估算
將取得的壓縮檔案解開後,可以看到以下六個目錄:

先進到一個目錄來觀察

對一個檔案按下內容

可以看到每個圖形寬度與長度都是 64 個圖素(pixels),每個圖素(pixels)占用8位元(bit),就是一個位元組(byte)
估算一下每張圖占用的空間:64*64*1=4096位元組(byte) = 4KB
假設每種圖片都是1000張,6種圖片有 6000 張,全部占用 6000*4KB=24MB
如果全部將 6000 張圖讀進記憶體來訓練會花費 24MB 的記憶體。依照目前的電腦環境還可以接受。
2. 資料讀取
了解資料的目錄結構和資料空間使用量,就可以準備讀取檔案了!
Python 裡面有個函式 os.path.join(dir,folder) 可以得到檔案的絕對路徑。
。而Python 裡面的 OpenCV 函式庫可以用來讀取圖片資料與圖片縮放。
程式可寫成
import os
import cv2 as cv
dir = os.path.join(target_dir, 'AbdomenCT')
images=[]
for image in os.listdir(dir): # going through all the images in different folders and resizing them
# read file in gray
image_read = cv.imread(os.path.join(dir, image), cv.IMREAD_GRAYSCALE)
images.append(image_read)
用 Debugger 觀察變數的資料

dir 是電腦裡的絕對路徑;image 是 '0000.jpg' ,

讀進來的檔案是 64x64

加入 image 陣列是 2維空間的資料,一個圖素(pixels)的大小是 unsigned int = byte
3. 組織資料
我們訓練資料的目的是要識別這張圖是 6 種圖形中的哪一種,因此是人工智慧裡的分類(classification)問題。
分類(classification)問題就有標準答案可供訓練,屬於監督式學習(supervised learning)。再看一下我們的目錄結構:

可以將 'AbdomenCT'目錄裡的資料都設為 0;
'BreastMRI'目錄裡的資料都設為 1。這樣就完成監督式學習(supervised learning)裡的標準答案了!
還好在 Python 裡面,list 結構可將裡面內容列出索引值(index)。索引值(index)就可以當作標準答案的編碼。
程式可以這樣寫:
FolderTitles = ['AbdomenCT',
'BreastMRI',
'ChestCT',
'CXR',
'Hand',
'HeadCT']
class_num = FolderTitles.index('AbdomenCT')
在加入 images 陣列時,可以將標準答案一起加入
images.append([image_read, class_num])
再觀察一下執行結果:

可以看到裡面加入圖片資料和標準答案
4. 圖片特徵2維轉1維
對於圖形的訓練資料,我們在送進訓練之前需要將2維資料轉換成1維。Python 處理資料時,橫向(row)是資料筆數,而縱向(column)是資料特徵。只要是同一張圖片資料,就應該在同一個縱向(column)排行裡面。

這裡可以看到,原始讀進的圖檔是 64*64
這裡為了降低資料量,先用 OpenCV 裡的一個函式將圖片資料縮小
nimage_size=32
image_resized = cv.resize(image_read, (nimage_size, nimage_size))

經過 cv.resize 後,圖片資料已經轉成 32x32

加了2筆資料後,可以看到有圖片資料和標準答案
5. 分割 x, y 特徵資料與答案資料及正規化
為了分割資料到 特徵資料和答案資料,要做以下的步驟。而且在圖片資料處理中還要加上正規化的步驟。
考慮到這6種醫學影像,彼此間的特徵不一致。很難用一致的標準來平均,所以這裡我使用sklearn.preprocessing 裡的 MinMaxScaler 來做正規化的工作。
X=[]
y=[]
from sklearn.preprocessing import MinMaxScaler
sc=MinMaxScaler()
for feature,label in imageFiles:
# feature scaling
feature = sc.fit_transform(feature)
X.append(feature)
y.append(label)
經過這段程式,X 是一維的矩陣

6. 資料組成轉換
送入訓練模型前,我們還需要對資料做轉換。這是 tensorflow / keras 的要求。tensorflow / keras 的要求是格式是 筆數,每筆資料長度。但目前 X 只有每筆資料長度。我們需要自行轉換。
幸好,Python 裡面的 numpy 函式庫有一個轉換函數:numpy.array(X).reshape()。
我們需要的目的是:筆數,每筆資料長度。而每筆資料長度 就是一張圖片的 寬度*長度。
前面,我們已經將寬度和長度改成了 32*32
,因此目前每筆資料長度 就是 32*32=1024
可以用以下的程式來改:
X = np.array(X).reshape(-1, (nimage_size*nimage_size))
改過後我們再觀察X 的資料分布:

X 的維度就改成 (58954, 1024),也就滿足tensorflow / keras 的要求了!
7. DNN 訓練及驗證
考慮到 一張圖片資料有1024個圖素(pixel),我在這裡設定一次學習是20張圖片(batch size=20)。
訓練資料集有 75% 的資料量:58954*75%=44215。 訓練次數(epochs)設到 10 次
訓練結果還算令人滿意:訓練資料集準確度達到 99.77%;

測試資料集準確度達到 99.51%。

99% 以上已經達到工業級的要求標準了!
訓練 10 次花費 1 分鐘 4 秒,還算是可以接受的時間。
請先 登入 以發表留言。