這次以卷積神經網路(Convolutional Neural Network)來學習並預測X光片影像資料中使用者可能得到肺炎的機率。
使用到 OpenCV 程式庫。

實作題目是中國大陸廣州婦幼醫院胸部肺炎診斷 X光片(Chest X-Ray for Pneumonia)

胸部X射線圖像(前後)選自廣州市婦幼保健中心的1至5歲兒科患者的回顧性研究。 所有胸部X射線影像都是患者常規臨床護理的一部分。

[資料說明]
數據集分為3個文件夾(訓練,測試,val),並包含每個圖像類別(肺炎/正常)的子文件夾。 有5,863張X射線圖像(JPEG)和2類(肺炎/正常)。
 

[資料視覺化]
在面對圖形相關處理時,OpenCV 是個好工具可以讓我們讀取與顯示圖片。我用以下的函式來檢視圖片:

def show_image(pathname):
    img = cv2.imread(pathname)
    cv2.imshow('image',img)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
    print(img.shape)

顯示的資訊是(1858,2090,3),表示原始的圖片是 1858*2090 ,還加上 3原色(R,G,B)的資料。這樣的資料對有限的電腦記憶體來說已經太大了!至於三原色的部分,在讀取影像時可以直接轉為灰階(gray scale)

讀到原圖 = cv.imread(路徑+檔名, cv.IMREAD_GRAYSCALE)

接下來我們需要縮小圖片(Downsizing)。還好在 OpenCV 程式庫裡面有一個 resize 函式可以直接使用:

改過後的影像 = cv.resize(讀到原圖, (縮小後長度,縮小後寬度)) # downsizing to 
這裡我將縮小後的長度和寬度設成 256*256

 

[資料的設置與讀取方式]
如資料夾所示,這裡有3個資料夾,其中每一個都有 NORMAL 和 PNEUMONIA 目錄。而未來預測時每一筆資料都有NORMAL 和 PNEUMONIA 的結果分類。因此在訓練時應該是每一筆資料都包含 資料 加上 正常/肺炎這兩種內容。在 Python 裡面我們可以用 串列(list) 的方式來包裝 [影像,0 或 1]
在 串列(list) 中可以使用 .index() 將內容順序改成 0,1的數字順序
labels = ['NORMAL', 'PNEUMONIA']
class_num = labels.index(label)

 

[送入訓練模型前的轉換]
X 只包含 訓練內容,而 y 只包含 one-hot encoding 的資料
因此這裡還要再做一次轉換。

目前的 train_set: (5216, 2)
X=(5863, 2)

目前的資料,每一筆是 (圖片內容,0/1)
可以用以下的迴路一次地將特徵與label 抓取到 X 和 y 兩個串列(list)裡:

for feature, lable in train_set:
  X.append(feature)
  y.append(lable)

X list(5840) y list(5840)

X_new = np.array(X).reshape(-1, 256,256,1)
每一個元素是 256,256,1:256 是寬度和長度,後面的1是顏色的灰階的部分(gray)
X_new = (5863,256,256,1)


y 的部分也一樣
y_new = np.array(y)
y_new = np.expand_dims(y_new, axis=1)
這裡多了一個維度,是為了配合影像資料 X_new 裡面有一個灰階的維度
y_new = (5840,1)

 

[CNN 模型的建立]
      基本的資料形式都建立好了,接下來就是建立模型。
1. 切割資料:將原始的特徵和 Label 切割為:訓練用特徵、測試用特徵、訓練用Label 和 測試用 Label 等4筆資料:
X_train, X_test, y_train, y_test = train_test_split(X_new, y_new, test_size=0.2, random_state = 32)

2. 特徵數字一般化(normalize)
將 訓練用特徵、測試用特徵 轉換成浮點數,再將數字範圍限制在 0 到 1 之間。在一般 JPG 影像裡面,每一個圖點(pixel) 都在 0 到 255 之間。只要除以最大值就可以限制在
0 到 1 之間。

X_train = X_train.astype('float32')
X_test = X_test.astype('float32')

# normalizing: 0..255 to 0..1
X_train = X_train / 255
X_test = X_test / 255

3. 輸出端設成  one-hot encoding 
訓練用Label 和 測試用 Label 都轉換成 one-hot encoding 
以方便 CNN 和 MLP模型的學習
y_train2 = tf.keras.utils.to_categorical(y_train, output_result)
y_test2 = tf.keras.utils.to_categorical(y_test, output_result)

4. 建立模型
  先以 Sequential()建立模型
model = tf.keras.models.Sequential()

CNN(Convolution Neural Network) 模型其實就是 利用濾鏡程序(Filters)抓出訓練資料中的特徵,再將這些特徵送入 多層感知神經網路(Multi-Layer Perceptron) 加以訓練的流程。

濾鏡程序(Filters) 共包含三種函式:Conv2D、MaxPool2D 和Dropout

Conv2D() 設定濾鏡的數量、濾鏡大小、和激發函數
MaxPool2D() 是取出濾鏡輸出的最大值作為圖型特徵
Dropout() 是取出圖型特徵後,刪掉過多的特徵值,以減少計算量

第一次使用 Conv2D() 要注意 輸入 輸入大小 input_shape=(256,256,1) 因為我們使用圖形當作輸入特徵,要加入 長、寬和色階,所以是 (256,256,1)

接下來就是 多層感知神經網路(Multi-Layer Perceptron) 的部分。

Flatten() 將 平面 2維的影響改成一維空間
Dense() 輸入神經層的神經元數量
compile() 放入損失函數、最佳化函數
fit()  啟動訓練模型、訓練模型後再預測準確率

 

[模型結構]

上圖是 模型的輸出結果,6百多萬個參數需要調整!

 

[模型輸出與精確度]

上圖是 訓練次數與準確率的曲線圖:次數越多,準確率越高

文章標籤
全站熱搜
創作者介紹
創作者 小木屋 的頭像
小木屋

小木屋

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