日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人工智能 > pytorch >内容正文

pytorch

【深度学习】实战深度学习检测疟疾

發布時間:2025/3/12 pytorch 59 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【深度学习】实战深度学习检测疟疾 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

作者 | Tommy

編譯 | VK
來源 | Towards Data Science

在這個項目中,我們將通過美國國立衛生研究院提供的一個數據集,從150名感染了惡性瘧原蟲寄生蟲的患者身上獲取27558張不同的細胞圖像,并與50名健康患者的細胞圖像混合,這些圖像可以通過這里的鏈接下載:

https://www.kaggle.com/iarunava/cell-images-for-detecting-malaria

我們的任務是建立一個機器學習/深度學習算法,能夠對檢測到的細胞是否被寄生蟲感染進行分類。

在這個項目中,我們將使用一種深度學習算法,即卷積神經網絡(Convolutional Neural Network, CNN)算法,它通過訓練來分類某個細胞的圖像是否被感染。由于這是一個超過330mb數據的大項目,我建議將其應用到jupiter Notebook中。

首先,我們需要導入必要的起始庫:

import?pandas?as?pd import?numpy?as?np import?os import?cv2 import?random

你之前可能使用panda.read_csv()導入csv格式的數據集,但是,由于所有數據都是png格式的,因此可能需要使用os和cv2庫以不同的方式導入它們。

OS是一個強大的Python庫,允許你與操作系統進行交互,無論操作系統是Windows、Mac OS還是Linux。

另一方面,cv2是一個專門設計用于解決各種計算機視覺問題,如讀取和加載圖像。

首先,我們需要設置一個變量來設置我們的路徑,因為我們以后會繼續使用它:

root?=?'../Malaria/cell_images/' in?=?'/Parasitized/' un?=?'/Uninfected/'

因此,從上面的路徑是名為“瘧疾(Malaria)”的文件夾是我的細胞圖像文件夾文件存儲的地方,這也是寄生和未感染細胞的圖像存儲的地方。這樣,我們就能更容易地操縱這些路徑。

現在讓我們操作系統列表目錄(“path”)函數列出被寄生和未受感染文件夾中的所有圖像,如下所示:

Parasitized?=?os.listdir(root+in) Uninfected?=?os.listdir(root+un)


使用OpenCV和Matplotlib顯示圖像

例如,與csv文件不同,我們只能使用pandas的函數head列出多個數據,df.head(10) 顯示10行數據,對于圖像,我們需要使用for循環和matplotlib庫來顯示數據。

因此,首先讓我們導入matplotlib并為每個寄生和未感染的細胞圖像繪制圖像,如下所示:

import?matplotlib.pyplot?as?plt

然后繪制圖像:

plt.figure(figsize?=?(12,24)) for?i?in?range(4):plt.subplot(1,?4,?i+1)img?=?cv2.imread(root+in+?Parasitized[i])plt.imshow(img)plt.title('PARASITIZED?:?1')plt.tight_layout() plt.show()plt.figure(figsize?=?(12,24)) for?i?in?range(4):plt.subplot(2,?4,?i+1)img?=?cv2.imread(root+un+?Uninfected[i+1])plt.imshow(img)plt.title('UNINFECTED?:?0')plt.tight_layout() plt.show()

因此,為了繪制圖像,我們需要matplotlib中的figure函數,然后我們需要根據figsize函數確定每個圖形的大小。

如上所示,其中第一個數字是寬度,第二個數字是高度。然后在for循環中,我們將使用i作為變量來迭代range()中指示的次數。

在本例中,我們將只顯示4個圖像。隨后,我們將使用library中的subplot函數來指示某個迭代的行數、列數和繪圖數,我們使用i+1來實現。

由于我們已經創建了子圖,但是子圖仍然是空的,因此,我們需要使用OpenCV庫,通過使用cv2.imread()函數導入圖像,并包括其中的路徑和變量i,這樣它將繼續循環到下一張圖片,直到提供的最大范圍為止。

最后,我們將cv2庫導入的圖像用plt.imshow()函數繪出,我們將獲得以下輸出:


將圖像和標簽分配到變量中

接下來,我們要將所有圖像(無論是寄生細胞圖像還是未感染細胞圖像)及其標簽插入到一個變量中,其中1表示寄生細胞,0表示未感染細胞。因此,首先,我們需要為圖像和標簽創建一個空變量。但在此之前,我們需要使用Keras的img_to_array()函數。

from?tensorflow.keras.preprocessing.image?import?img_to_array

假設存儲圖像的變量稱為data,存儲標簽的變量稱為labels,那么我們可以執行以下代碼:

data?=?[] labels?=?[]for?img?in?Parasitized:try:img_read?=?plt.imread(root+in+?img)img_resize?=?cv2.resize(img_read,?(100,?100))img_array?=?img_to_array(img_resize)data.append(img_array)labels.append(1)except:Nonefor?img?in?Uninfected:try:img_read?=?plt.imread(root+un+?img)img_resize?=?cv2.resize(img_read,?(100,?100))img_array?=?img_to_array(img_resize)data.append(img_array)labels.append(0)except:None

在為空數組賦值變量數據和標簽之后,我們需要使用for循環插入每一張圖像。

這里有一些不同之處,for循環中還包含了try和except。try用于在for循環中正常運行代碼,另一方面,except用于代碼遇到錯誤或崩潰時,以便代碼可以繼續循環。

與上面的圖像顯示代碼類似,我們可以使用plt.imread(“path”)函數,但這一次,我們不需要顯示任何子圖。

你可能想知道我們為什么用plt.imread()而不是cv2.imread()。它們的功能是一樣的,事實上,還有很多其他的圖像讀取庫,例如,Pillow庫的image.open()或Scikit-Image庫的io.imread()。

然而,OpenCV以BGR或藍、綠、紅的順序讀取圖像,這就是為什么上面顯示的圖像是藍色的,盡管實際的圖片是粉色的。因此,我們需要使用以下代碼將其轉換回RGB順序:

cv2.cvtColor(img,?cv2.COLOR_BGR2RGB)

另一方面,Matplotlib、Scikit Image和Pillow Image reading函數會自動按RGB順序讀取圖像,因此,對于我們的單元格圖像實際顏色,我們不需要再進行轉換:

plt.imshow(data[0]) plt.show()

之后,我們可以通過使用OpenCV的cv2.resize()函數來調整圖像的大小,以將加載的圖像設置為一個特定的高度和寬度,如上面所示的100 width和100 height。

接下來,因為我們的圖像是抽象格式的,我們以后將無法對其進行訓練、測試或將其插入變量中,因此,我們需要使用keras的img_to_array()函數將其轉換為數組格式。這樣,我們就可以使用.append()函數將每個圖像插入變量的方括號中,該函數用于在不改變原始狀態的情況下將對象插入數組的最后一個列表。

所以在我們的循環中,我們不斷地在每個循環中添加一個新的圖像。


預處理數據

不像機器學習項目,我們可以立即分割我們的數據,在深入學習,特別是神經網絡,以減少方差,并減少過擬合。在Python中,有許多方法可以隨機化數據,比如使用Sklearn,如下所示:

from?sklearn.utils?import?shuffle

或使用如下所示的隨機方法:

from?random?import?shuffle

但在這個項目中,我們將使用Numpy的隨機函數。因此,我們需要將數組轉換成Numpy的數組函數,然后對圖像數據進行隨機化,如下所示:

image_data?=?np.array(data) labels?=?np.array(labels)idx?=?np.arange(image_data.shape[0]) np.random.shuffle(idx) image_data?=?image_data[idx] labels?=?labels[idx]

首先,我們將數據和標簽變量轉換為Numpy格式。然后,我們可以使用np.arange()然后使用np.random.shuffle()功能。最后,我們將被隨機數據重新分配到它們的原始變量中,以確保被隨機的數據被保存。


用于訓練、測試和驗證的拆分數據

在數據被隨機之后,我們應該通過導入必要的庫將它們拆分為訓練、測試和驗證標簽和數據,如下所示:

from?tensorflow.keras.utils?import?to_categorical from?sklearn.model_selection?import?train_test_split

然后我們設置一個函數,將數據轉換為32位數據以保存:

def?prep_dataset(X,y):X_prep?=?X.astype('float32')/255y_prep?=?to_categorical(np.array(y))return?(X_prep,?y_prep)

然后通過使用Sklearn庫,我們可以將數據分為訓練、測試和驗證:

X_tr,?X_ts,?Y_tr,?Y_ts?=?train_test_split(image_data,labels,?test_size=0.15,?shuffle=True,stratify=labels,random_state=42) X_ts,?X_val,?Y_ts,?Y_val?=?train_test_split(X_ts,Y_ts,?test_size=0.5,?stratify=Y_ts,random_state=42)X_tr,?Y_tr?=?prep_dataset(X_tr,Y_tr) X_val,?Y_val?=?prep_dataset(X_val,Y_val) X_ts,?_?=?prep_dataset(X_ts,Y_ts)

由于存在驗證數據,因此需要執行兩次拆分。在spliting函數中,我們需要在前兩個參數中分配數據和標簽,然后告訴它們被劃分成的百分比,隨機狀態是為了確保它們產生的數據總是以一致的順序排列。


卷積神經網絡模型的建立

在建立CNN模型之前,讓我們從理論上對它有一點更深入的了解。CNN主要應用于圖像分類,自1998年發明以來,由于其高性能和高精度,一直受到人們的歡迎。那么它是如何工作的呢?

正如我們從上面的插圖中看到的,CNN對圖像進行分類,取圖像的一部分,并將其通過幾層卷積處理來分類圖像。從這幾個層中,可以將它們分為三種類型的層,分別是卷積層、池化層和全連接層。

卷積層

第一層,卷積層是CNN最重要的方面之一,它的名字來源于此。其目的是利用核函數從輸入圖像中提取特征。該核將使用點積連續掃描輸入圖像,創建一個新的分析層,稱為特征圖/激活圖。其機理如下:

2*1 + 4*2 + 9*3 + 2*(-4) + 1*7 + 4*4 + 1*2 + 1*(-5) + 2*1 = 51

然后繼續,直到所有特征圖的單元格都被填滿。

池化層

在我們創建了特征圖之后,我們將應用一個池化層來減小其大小以減少過擬合。此步驟中有幾個操作,但是,最流行的技術是最大池,其中特征圖的掃描區域將僅取最高值,如下圖所示:

卷積和池的步驟可以重復,直到理想的大小是最后敲定,然后我們可以繼續分類部分,它被稱為全連接層。

全連通層

在這一階段,變換后的特征圖將被展平為一個列向量,該列向量將在每個迭代過程中經過前饋神經網絡和反向傳播過程,持續數個階段。最后,CNN模型將區分主要特征和非主要特征,利用Softmax分類對圖像進行分類。

在Python中,我們需要從Keras庫導入CNN函數:

from?tensorflow.keras?import?models,?layers from?tensorflow.keras.callbacks?import?EarlyStopping

然后,我們將構建我們自己的CNN模型,包括4個卷積層和池化層:

model?=?models.Sequential()#Input?+?Conv?1?+?ReLU?+?Max?Pooling model.add(layers.Conv2D(32,(5,5),activation='relu',padding='same',input_shape=X_tr.shape[1:]))model.add(layers.MaxPool2D(strides=4)) model.add(layers.BatchNormalization())#?Conv?2?+?ReLU?+?Max?Pooling model.add(layers.Conv2D(64,(5,5),padding='same',activation='relu'))model.add(layers.MaxPool2D(strides=2)) model.add(layers.BatchNormalization())#?Conv?3?+?ReLU?+?Max?Pooling model.add(layers.Conv2D(128,(3,3),padding='same',activation='relu'))model.add(layers.MaxPool2D(strides=2)) model.add(layers.BatchNormalization())#?Conv?4?+?ReLU?+?Max?Pooling model.add(layers.Conv2D(256,(3,3),dilation_rate=(2,2),padding='same',activation='relu')) model.add(layers.Conv2D(256,(3,3),activation='relu')) model.add(layers.MaxPool2D(strides=2)) model.add(layers.BatchNormalization())#?Fully?Connected?+?ReLU model.add(layers.Flatten())model.add(layers.Dense(300,?activation='relu')) model.add(layers.Dense(100,?activation='relu'))#Output model.add(layers.Dense(2,?activation='softmax'))model.summary()

Keras中的卷積層

好的,在這段代碼中,你可能會感到困惑的第一件事是model .sequential()。

利用Keras構建深度學習模型有兩種選擇,一種是序列模型,另一種是函數模型。他們兩人之間的差異是序列模型只允許一層一層地建立一個模型,另一方面,函數模型允許層連接到前一層,多層,甚至任何層,你想建立一個更復雜的模型。由于我們正在構建一個簡單的CNN模型,所以我們將使用序列模型。

我們之前了解到,CNN由卷積層組成,卷積層后來使用池化層進行簡化,因此,我們需要使用Keras函數model.add()添加層,然后添加我們喜歡的層。

由于我們的圖像是2D形式,我們只需要2D卷積層,同樣使用卷積層的Keras函數:layers.Conv2D(). 正如你在每一層所看到的,第一層有一個數字32,第二層有一個數字64,乘以2并以此類推。這叫做濾波器。它所做的是試圖捕捉圖像的模式。

因此,隨著濾波器尺寸的增大,我們可以在較小的圖像上捕獲更多的模式,盡管沒有太多理論的證明,然而,這被認為是最優方法。

接下來,(5,5)和(3,3)矩陣是我們上面討論的用于創建特征圖的核。然后這里有兩個有趣的部分:ReLu的激活和填充。那些是什么?我們先來討論ReLu。它是由Rectified Linear Unit縮短而來的,其想法是采用更簡單的模型,提高訓練過程的效率。

下一個問題是填充。如我們所知,卷積層不斷減小圖像的大小,因此,如果我們在新的特征圖的所有四個邊上添加填充,我們將保持相同的大小。所以我們在處理后的圖像周圍添加新的單元格,值為0,以保持圖像的大小。填充有兩個選項:相同或零。接下來就是input_shape,它只是我們的輸入圖像,只在第一層中用于輸入我們的訓練數據。

Keras中的池化層

讓我們轉到池化層,我們可以使用Keras的layers.MaxPool2D()。這里有一種東西叫做跨步(stride)。它是核將在輸入上每次移動的步數。因此,如果我們用5x5的核,并且跨步為4,核將計算圖像最左邊的部分,然后跳過右邊的4個單元格來執行下一次計算。

你可能會注意到,每個卷積層和池化層都以批標準化結束。為什么?因為在每一層中,都有不同的分布,訓練過程會變慢,因為它需要適應每一層。但是,如果強制所有層具有相似的分布,則可以跳過此步驟并提高訓練速度。這就是為什么我們在每一層中應用批標準化,通過如下所示的4個步驟對每一層中的輸入進行標準化:

Keras全連接層

現在我們已經到了CNN的最后階段,也就是全連接的階段。但在進入這個階段之前,由于我們將在全連接階段使用“Dense”層,所以我們需要使用Keras層將處理過的數據平鋪成一維。Flatten()函數用于將垂直和水平的數據合并到單個列中。

我們將數據展平后,現在需要使用layers.Dense()函數將它們全連接起來,然后指定要用作輸出的神經元數量,考慮到當前的神經元是1024個。所以我們先使用300個神經元,然后是100個神經元,并使用ReLu對其進行優化。

最后,我們到達輸出階段,這也是通過使用Dense函數來完成的,然而,由于我們的分類只有2個概率,即感染瘧疾或未感染瘧疾,因此,我們將輸出單位設置為2。此外,在分類任務中,我們在輸出層使用Softmax激活而不是ReLu,因為ReLu將所有負類設置為零。

綜上所述,我們構建的模型如下:

然后,我們將把我們的訓練和驗證數據整合到模型中:

model.compile(optimizer='adam',loss='categorical_crossentropy',metrics=['accuracy'])es?=?EarlyStopping(monitor='val_accuracy',mode='max',patience=3,verbose=1)history=?model.fit(X_tr,Y_tr,epochs=20,batch_size=50,validation_data=(X_val,Y_val),callbacks=[es])

由于數據量很大,這個過程需要一些時間。如下圖所示,每個epoch平均運行9分鐘。


評估

我們可以通過繪制評估圖來評估模型性能,但在此之前,我們需要導入seaborn庫:

import?seaborn?as?sns

然后將準確度和損失繪制如下:

fig,?ax=plt.subplots(2,1,figsize=(12,10)) fig.suptitle('Train?evaluation')sns.lineplot(ax=?ax[0],x=np.arange(0,len(history.history['accuracy'])),y=history.history['accuracy']) sns.lineplot(ax=?ax[0],x=np.arange(0,len(history.history['accuracy'])),y=history.history['val_accuracy'])ax[0].legend(['Train','Validation']) ax[0].set_title('Accuracy')sns.lineplot(ax=?ax[1],x=np.arange(0,len(history.history['loss'])),y=history.history['loss']) sns.lineplot(ax=?ax[1],x=np.arange(0,len(history.history['loss'])),y=history.history['val_loss'])ax[1].legend(['Train','Validation']) ax[1].set_title('Loss')plt.show()

這將給我們一個輸出:

它的平均性能似乎超過90%,這是非常好的,正如CNN模型所預期的。不過,為了讓我們更具體地了解數據性能,讓我們使用Sklearn構建一個混淆矩陣,并預測輸出:

from?sklearn.metrics?import?confusion_matrix,?accuracy_scoreY_pred?=?model.predict(X_ts)Y_pred?=?np.argmax(Y_pred,?axis=1)conf_mat?=?confusion_matrix(Y_ts,Y_pred)sns.set_style(style='white') plt.figure(figsize=(12,8)) heatmap?=?sns.heatmap(conf_mat,vmin=np.min(conf_mat.all()),?vmax=np.max(conf_mat),?annot=True,fmt='d',?annot_kws={"fontsize":20},cmap='Spectral') heatmap.set_title('Confusion?Matrix?Heatmap\n?Is?the?cell?infected?',?fontdict={'fontsize':15},?pad=12) heatmap.set_xlabel('Predicted',fontdict={'fontsize':14}) heatmap.set_ylabel('Actual',fontdict={'fontsize':14}) heatmap.set_xticklabels(['NO','YES'],?fontdict={'fontsize':12}) heatmap.set_yticklabels(['NO','YES'],?fontdict={'fontsize':12}) plt.show()print('-Acuracy?achieved:?{:.2f}%\n-Accuracy?by?model?was:?{:.2f}%\n-Accuracy?by?validation?was:?{:.2f}%'.format(accuracy_score(Y_ts,Y_pred)*100,(history.history['accuracy'][-1])*100,(history.history['val_accuracy'][-1])*100))

這將為我們提供以下準確度:


錯誤樣本

讓我們看看錯誤示例的樣子:

index=0 index_errors=?[]for?label,?predict?in?zip(Y_ts,Y_pred):if?label?!=?predict:index_errors.append(index)index?+=1plt.figure(figsize=(20,8))for?i,img_index?in?zip(range(1,17),random.sample(index_errors,k=16)):plt.subplot(2,8,i)plt.imshow(np.reshape(255*X_ts[img_index],?(100,100,3)))plt.title('Actual:?'+str(Y_ts[img_index])+'?Predict:?'+str(Y_pred[img_index])) plt.show()

輸出:

盡管未感染,但錯誤的預測圖像似乎包含了細胞上的幾個紫色斑塊,因此,模型實際預測它們為感染細胞是可以理解的。

我想說CNN是一個非常強大的圖像分類模型,不需要做很多預處理任務,因為處理包含在卷積層和池化層中。

希望通過本文的學習,讓你能夠利用卷積神經網絡進行圖像分類。

感謝你的閱讀。

?------------------------------------------------

看到這里,說明你喜歡這篇文章,請點擊「在看」或順手「轉發」「點贊」。

往期精彩回顧適合初學者入門人工智能的路線及資料下載機器學習及深度學習筆記等資料打印機器學習在線手冊深度學習筆記專輯《統計學習方法》的代碼復現專輯 AI基礎下載機器學習的數學基礎專輯溫州大學《機器學習課程》視頻 本站qq群851320808,加入微信群請掃碼:

總結

以上是生活随笔為你收集整理的【深度学习】实战深度学习检测疟疾的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。