Title.png

  在一般的圖形識別中,Google 資料集的 MNIST 是很好的資料。而在醫學影像識別中也有很多的影像圖片。這裡將醫學中常見的六種影像:腹部電腦斷層、胸腔磁共振造影、胸部電腦斷層、胸部 X 光、手部 X 光及頭部 X 光集合起來來做影像辨識(classification)的工作。本文紀錄處理圖片資料的預先處裡流程,最後結合深度學習框架Tensorflow 及 keras 完成深度學習中的分類(classification)工作。

1. 資料放置位置與記憶體空間估算

  將取得的壓縮檔案解開後,可以看到以下六個目錄:
1_1_Folders.png

  先進到一個目錄來觀察

1_2_Files.png

  對一個檔案按下內容

1_4_size64_8bits.png

 

可以看到每個圖形寬度與長度都是 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 觀察變數的資料
2_1_codeVar.png

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

  讀進來的檔案是 64x64 

2_3_codeVar_2Dappend.png

  加入 image 陣列是 2維空間的資料,一個圖素(pixels)的大小是 unsigned int = byte

 

3. 組織資料

   我們訓練資料的目的是要識別這張圖是 6 種圖形中的哪一種,因此是人工智慧裡的分類(classification)問題。

  分類(classification)問題就有標準答案可供訓練,屬於監督式學習(supervised learning)。再看一下我們的目錄結構:
1_1_Folders.png

  可以將 '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])

再觀察一下執行結果:
3_1_add2items.png

可以看到裡面加入圖片資料和標準答案

4. 圖片特徵2維轉1維

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

4_1_read_64_64size.png

這裡可以看到,原始讀進的圖檔是 64*64


  這裡為了降低資料量,先用 OpenCV 裡的一個函式將圖片資料縮小

nimage_size=32
image_resized = cv.resize(image_read, (nimage_size, nimage_size))

4_2_resize_32_32.png

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

4_4_add2items.png

加了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 是一維的矩陣

5_3_X_afterScaled_1D.png

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 的資料分布:
5_4_X_afterReshape_RowCol_58____1024.png

 X 的維度就改成 (58954, 1024),也就滿足tensorflow / keras 的要求了!


7. DNN 訓練及驗證

  考慮到 一張圖片資料有1024個圖素(pixel),我在這裡設定一次學習是20張圖片(batch size=20)

  訓練資料集有 75% 的資料量:58954*75%=44215。 訓練次數(epochs)設到 10

訓練結果還算令人滿意:訓練資料集準確度達到 99.77%

7_1_model_train_acc.png

 

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

7_1_test_acc.png

 

99% 以上已經達到工業級的要求標準了!

  訓練 10 次花費 1 分鐘 4 秒,還算是可以接受的時間。
 

 

創作者介紹
創作者 小木屋 的頭像
小木屋

小木屋

小木屋 發表在 痞客邦 留言(0) 人氣( 543 )