? ? ? ? 大家好,我是帶我去滑雪!
? ? ? ? 影像組學作為近年來醫學影像分析領域的重要研究方向,致力于通過從醫學圖像中高通量提取大量定量特征,以輔助疾病診斷、分型、預后評估及治療反應預測。這些影像特征涵蓋了形狀、紋理、灰度統計及波形變換等多個維度,能夠在無需侵入性操作的前提下,為臨床提供潛在的生物標志物。相比于傳統醫生的主觀評估,影像組學特征更加客觀、量化,能捕捉到肉眼難以察覺的圖像差異,從而提升疾病識別的敏感性與特異性。然而,隨著特征數量和維度的不斷增加,如何從海量數據中有效提取具有判別力的高階特征,成為制約影像組學發展的關鍵問題。傳統的手工特征提取方法依賴于專家經驗設計,往往具有局限性,難以適應復雜多變的臨床場景。此時,深度學習技術的引入為影像組學的發展帶來了新的突破。特別是卷積神經網絡(CNN)在圖像處理方面的卓越表現,為自動化特征提取提供了有力工具。
? ? ? ? ?在眾多CNN架構中,ResNet(殘差網絡)因其獨特的殘差連接機制,有效緩解了網絡加深帶來的梯度消失問題,能夠訓練更深層次的模型,從而捕捉更復雜、抽象的影像特征。相比淺層網絡或傳統方法,ResNet能自動從原始圖像中學習出更具區分性的表征,提升分類和預測性能。在影像組學應用中,ResNet不僅可以代替手工特征提取過程,還能與傳統特征融合,實現更高層次的特征整合,增強模型的泛化能力。因此,將ResNet應用于影像組學特征提取,不僅符合當前智能醫療發展的趨勢,也為精準醫學提供了強有力的技術支撐。
? ? ? ?這里使用公開的肺炎X-ray數據集,數據集包含5856張經過驗證的胸部X光片圖像,且被分為訓練集和獨立患者的測試集。數據集中所有文件已經被轉換為JPEG格式,并且已經被劃分為正常、肺炎兩個類別。
? ? ? ? ResNet模型提取影響特征代碼:
import os
import numpy as np
import pandas as pd
from glob import glob
from PIL import Image
from tqdm import tqdm
from sklearn.decomposition import PCA
from matplotlib import pyplot as pltimport torch
from torchvision.models import resnet50, ResNet50_Weights
from torchvision.models.feature_extraction import get_graph_node_names
from torchvision.models.feature_extraction import create_feature_extractor
from torchvision import transforms# 用于遍歷圖像
def images_iterator(image_dir):dataset_images = glob(f"{image_dir}/**/*.jpeg", recursive=True)for image_path in dataset_images:file_name = os.path.basename(image_path).split(".")[0]image = Image.open(image_path)# Resnet在預訓練使用的參數imagenet_mean = [0.485, 0.456, 0.406]imagenet_std = [0.229, 0.224, 0.225]# 參照Resnet預訓練時的圖像處理方式處理transform = transforms.Compose([# 轉換為 Tensor,自動將像素值歸一化到 [0, 1]transforms.ToTensor(),# 調整大小transforms.Resize((224, 224)),# resnet輸入要求通道數量為3transforms.Lambda(lambda x: x.repeat(3, 1, 1) if x.size(0) == 1 else x),# 對像素取值歸一化transforms.Normalize(mean=imagenet_mean,std=imagenet_std)])input_tensor = transform(image)input_tensor = input_tensor.unsqueeze(0)# dimensions of input_tensor are [1, 3, 224, 224]# 返回文件名和預處理之后的圖像yield file_name, input_tensordef pca_plot(csv_path="./test.csv"):# 加載提出的特征df_data = pd.read_csv(csv_path)df_x = df_data.iloc[:, 2:].to_numpy()df_y = df_data.iloc[:, 1].to_numpy()# 通過PCA算法將Resnet提取的2048個特征降為3個pca = PCA(n_components=3)x = pca.fit(df_x).transform(df_x)# 繪制圖像的一些參數設置category_names = ["NORMAL", "PNEUMONIA"]ax = plt.figure().add_subplot(projection='3d')colors = ["navy", "turquoise"]lw = 2# 繪制圖像for color, target_name in zip(colors, category_names):ax.scatter(x[df_y == target_name, 0],x[df_y == target_name, 1],x[df_y == target_name, 2],color=color, alpha=0.8,lw=lw,label=target_name)plt.title("PCA of Chest X-ray")plt.show()def main():# 加載預訓練的resnet50模型resnet50_weight = ResNet50_Weights.DEFAULTprint(resnet50_weight.transforms())resnet50_mdl = resnet50(weights=ResNet50_Weights.DEFAULT).eval()# 輸出每一層的名稱nodes_name, _ = get_graph_node_names(resnet50_mdl)# 根據輸出結果,我們可以知道resnet50在通過全連接層分類之前的網絡層名稱是flattenprint(nodes_name)return_nodes = {"flatten": "final_feature_map"}# 基于選擇的輸出和resnet50構建特征提取器feature_extracter = create_feature_extractor(resnet50_mdl, return_nodes=return_nodes)# 設定影像路徑chest_xray = os.path.join(os.getcwd(), "chest_xray")train_dataset_dir = os.path.join(chest_xray, "train")test_dataset_dir = os.path.join(chest_xray, "test")# 設定列名column_names = ["patient_id", "category"] + [f"resnet_feature_{i + 1}" for i in range(2048)]with torch.no_grad():df_train = pd.DataFrame()df_test = pd.DataFrame()# 進行訓練集印象特征提取for image_name, image_tensor in tqdm(images_iterator(train_dataset_dir)):# dimensions of out is [1, 2048]out = feature_extracter(image_tensor)out_features = out["final_feature_map"]out_features = out_features.cpu().numpy()[0]if "NORMAL" in image_name:category = "NORMAL"else:category = "PNEUMONIA"row_data = [image_name, category] + list(out_features)df_train = pd.concat([df_train, pd.Series(row_data)], ignore_index=True, axis=1)# 保存到csv文件df_train = df_train.Tdf_train.columns = column_namesdf_train.to_csv("train.csv", index=False)# 進行測試集影像特征提取for image_name, image_tensor in tqdm(images_iterator(test_dataset_dir)):# dimensions of out is [1, 2048]out = feature_extracter(image_tensor)out_features = out["final_feature_map"]out_features = out_features.cpu().numpy()[0]if "NORMAL" in image_name:category = "NORMAL"else:category = "PNEUMONIA"row_data = [image_name, category] + list(out_features)df_test = pd.concat([df_test, pd.Series(row_data)], ignore_index=True, axis=1)# 保存到csv文件df_test = df_test.Tdf_test.columns = column_namesdf_test.to_csv("test.csv", index=False)if __name__ == "__main__":main()pca_plot()
? ? ? ?輸出結果:
? ? ? ? ?使用ResNet模型提取的影像特征和傳統方法提取的影像特征是一樣的,最主要的區別只是深度學習算法提取的特征沒有名稱。獲取ResNet提取的特征之后,就可以使用其它統計分析方法進行下一步分析。下面使用PCA對提取的特征進行降維,并進行可視化:
更多優質內容持續發布中,請移步主頁查看。
? ?點贊+關注,下次不迷路!