Main.py 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. import os
  2. import time
  3. import torch.multiprocessing as mp
  4. import matplotlib.pyplot as plt
  5. import numpy as np
  6. from ChexnetTrainer import ChexnetTrainer
  7. from DatasetGenerator import DatasetGenerator
  8. from visual import HeatmapGenerator
  9. # 确保 images 目录存在
  10. if not os.path.exists('images'):
  11. os.makedirs('images')
  12. # 主函数,负责启动不同的功能(训练、测试或运行演示)
  13. def main():
  14. # runDemo() # 运行演示模式
  15. # runTest() # 测试模式(注释掉,可以通过解除注释来运行)
  16. runTrain() # 训练模式(注释掉,可以通过解除注释来运行)
  17. # --------------------------------------------------------------------------------
  18. # 训练函数,定义训练所需的参数并启动模型训练
  19. def runTrain():
  20. DENSENET121 = 'DENSE-NET-121' # 定义DenseNet121模型名称
  21. DENSENET169 = 'DENSE-NET-169' # 定义DenseNet169模型名称
  22. DENSENET201 = 'DENSE-NET-201' # 定义DenseNet201模型名称
  23. Resnet50 = 'RESNET-50' # 定义Resnet50模型名称
  24. # 获取当前的时间戳,作为训练过程的标记
  25. timestampTime = time.strftime("%H%M%S")
  26. timestampDate = time.strftime("%d%m%Y")
  27. timestampLaunch = timestampDate + '-' + timestampTime
  28. print("Launching " + timestampLaunch)
  29. # 图像数据所在的路径
  30. pathDirData = './chest xray14'
  31. # 训练、验证和测试数据集文件路径
  32. # 每个文件中包含图像路径及其对应的标签
  33. pathFileTrain = './dataset/train_2.txt'
  34. pathFileVal = './dataset/valid_2.txt'
  35. pathFileTest = './dataset/test_2.txt'
  36. # 神经网络参数:模型架构、是否加载预训练模型、分类的类别数量
  37. nnArchitecture = DENSENET121
  38. nnIsTrained = True # 使用预训练的权重
  39. nnClassCount = 14 # 数据集包含14个分类
  40. # 训练参数:批量大小和最大迭代次数(epochs)
  41. trBatchSize = 2
  42. trMaxEpoch = 2
  43. # 图像预处理相关参数:图像缩放的大小和裁剪后的大小
  44. imgtransResize = 256
  45. imgtransCrop = 224
  46. # 保存模型的路径,包含时间戳
  47. pathModel = 'm-' + timestampLaunch + '.pth.tar'
  48. print('Training NN architecture = ', nnArchitecture)
  49. ChexnetTrainer.train(pathDirData, pathFileTrain, pathFileVal,
  50. nnArchitecture, nnIsTrained, nnClassCount, trBatchSize,
  51. trMaxEpoch, imgtransResize, imgtransCrop,
  52. timestampLaunch, None)
  53. print('Testing the trained model')
  54. pathRfModel = os.path.join('images', 'random_forest_model.pkl') # 更新路径
  55. labels, rf_preds = ChexnetTrainer.test(pathDirData, pathFileTest, pathModel, pathRfModel, nnArchitecture,
  56. nnClassCount, nnIsTrained, trBatchSize, imgtransResize,
  57. imgtransCrop, timestampLaunch)
  58. # 生成并保存热力图
  59. # 选择一些测试集中的样本来生成热力图
  60. transformSequence = ChexnetTrainer._get_transform(imgtransCrop)
  61. datasetTest = DatasetGenerator(pathImageDirectory=pathDirData, pathDatasetFile=pathFileTest,
  62. transform=transformSequence, model=None)
  63. # 确保测试集中有足够的样本
  64. num_samples = min(8, len(datasetTest))
  65. sample_indices = np.random.choice(len(datasetTest), size=num_samples, replace=False) # 随机选择8个样本
  66. # 定义分类名称
  67. CLASS_NAMES = ['Atelectasis', 'Cardiomegaly', 'Effusion',
  68. 'Infiltration', 'Mass', 'Nodule', 'Pneumonia',
  69. 'Pneumothorax', 'Consolidation', 'Edema', 'Emphysema',
  70. 'Fibrosis', 'Pleural_Thickening',
  71. 'Hernia']
  72. # 创建一个图形窗口
  73. plt.figure(figsize=(20, 10))
  74. n_cols = 4
  75. n_rows = 2
  76. for idx, sample_idx in enumerate(sample_indices):
  77. image_path = datasetTest.listImagePaths[sample_idx]
  78. true_labels = labels[sample_idx]
  79. pred_labels = rf_preds[sample_idx]
  80. # 加载图像
  81. img = plt.imread(image_path)
  82. # 创建子图
  83. ax = plt.subplot(n_rows, n_cols, idx + 1)
  84. ax.imshow(img)
  85. ax.axis('off')
  86. # 获取真实标签和预测标签的名称
  87. true_label_names = [CLASS_NAMES[i] for i in range(len(true_labels)) if true_labels[i] == 1]
  88. pred_label_names = [CLASS_NAMES[i] for i in range(len(pred_labels)) if pred_labels[i] == 1]
  89. # 设置标题
  90. title = f"Predicted: {', '.join(pred_label_names)}\nTrue: {', '.join(true_label_names)}"
  91. ax.set_title(title, fontsize=10)
  92. plt.tight_layout()
  93. output_plot_path = os.path.join('images', 'test_predictions.png')
  94. plt.savefig(output_plot_path)
  95. plt.show()
  96. print(f"预测结果图已保存到 {output_plot_path}")
  97. # 生成热力图(可选)
  98. for idx in sample_indices:
  99. image_path = datasetTest.listImagePaths[idx]
  100. output_heatmap_path = os.path.join('images', f'heatmap_test_{idx}.png')
  101. h = HeatmapGenerator(pathModel, nnArchitecture, nnClassCount, imgtransCrop, transformSequence)
  102. h.generate(image_path, output_heatmap_path, imgtransCrop)
  103. print(f"热力图已保存到 {output_heatmap_path}")
  104. # --------------------------------------------------------------------------------
  105. # 测试函数,加载预训练模型并在测试数据集上进行测试
  106. def runTest():
  107. pathDirData = '/chest xray14'
  108. pathFileTest = './dataset/test.txt'
  109. nnArchitecture = 'DENSE-NET-121'
  110. nnIsTrained = True
  111. nnClassCount = 14
  112. trBatchSize = 4
  113. imgtransResize = 256
  114. imgtransCrop = 224
  115. pathModel = 'm-06102024-235412BCELoss()delete.pth.tar'
  116. timestampLaunch = ''
  117. # 获取统一的 transformSequence
  118. transformSequence = ChexnetTrainer._get_transform(imgtransCrop)
  119. pathRfModel = 'images/random_forest_model.pkl' # 确保路径正确
  120. labels, rf_preds = ChexnetTrainer.test(pathDirData, pathFileTest, pathModel, pathRfModel, nnArchitecture,
  121. nnClassCount, nnIsTrained, trBatchSize, imgtransResize,
  122. imgtransCrop, timestampLaunch)
  123. # 生成并保存热力图
  124. datasetTest = DatasetGenerator(pathImageDirectory=pathDirData, pathDatasetFile=pathFileTest,
  125. transform=transformSequence, model=None)
  126. # 确保测试集中有足够的样本
  127. num_samples = min(8, len(datasetTest))
  128. sample_indices = np.random.choice(len(datasetTest), size=num_samples, replace=False) # 随机选择8个样本
  129. # 定义分类名称
  130. CLASS_NAMES = ['Atelectasis', 'Cardiomegaly', 'Effusion',
  131. 'Infiltration', 'Mass', 'Nodule', 'Pneumonia',
  132. 'Pneumothorax', 'Consolidation', 'Edema', 'Emphysema',
  133. 'Fibrosis', 'Pleural_Thickening',
  134. 'Hernia']
  135. # 创建一个图形窗口
  136. plt.figure(figsize=(20, 10))
  137. n_cols = 4
  138. n_rows = 2
  139. for idx, sample_idx in enumerate(sample_indices):
  140. image_path = datasetTest.listImagePaths[sample_idx]
  141. true_labels = labels[sample_idx]
  142. pred_labels = rf_preds[sample_idx]
  143. # 加载图像
  144. img = plt.imread(image_path)
  145. # 创建子图
  146. ax = plt.subplot(n_rows, n_cols, idx + 1)
  147. ax.imshow(img)
  148. ax.axis('off')
  149. # 获取真实标签和预测标签的名称
  150. true_label_names = [CLASS_NAMES[i] for i in range(len(true_labels)) if true_labels[i] == 1]
  151. pred_label_names = [CLASS_NAMES[i] for i in range(len(pred_labels)) if pred_labels[i] == 1]
  152. # 设置标题
  153. title = f"Predicted: {', '.join(pred_label_names)}\nTrue: {', '.join(true_label_names)}"
  154. ax.set_title(title, fontsize=10)
  155. plt.tight_layout()
  156. output_plot_path = os.path.join('images', 'test_predictions.png')
  157. plt.savefig(output_plot_path)
  158. plt.show()
  159. print(f"预测结果图已保存到 {output_plot_path}")
  160. # 生成热力图(可选)
  161. for idx in sample_indices:
  162. image_path = datasetTest.listImagePaths[idx]
  163. output_heatmap_path = os.path.join('images', f'heatmap_test_{idx}.png')
  164. h = HeatmapGenerator(pathModel, nnArchitecture, nnClassCount, imgtransCrop, transformSequence)
  165. h.generate(image_path, output_heatmap_path, imgtransCrop)
  166. print(f"热力图已保存到 {output_heatmap_path}")
  167. # --------------------------------------------------------------------------------
  168. # 演示函数,展示模型在测试集上的推理过程
  169. def runDemo():
  170. # 原有代码保持不变
  171. pass
  172. # 确保代码在主进程中运行
  173. if __name__ == '__main__':
  174. mp.set_start_method('spawn', force=True)
  175. main() # 启动主函数