def test(**kwargs): config.parse(kwargs) # prepare data test_data = Vertebrae_Dataset( config.data_root, config.test_paths, phase='test') # 注意这里不要加balance=False,否则生成的Dataset会包含混合型 test_dataloader = DataLoader(test_data, batch_size=config.batch_size, shuffle=False, num_workers=config.num_workers) # test_data = FrameDiff_Dataset(config.data_root, config.test_paths, phase='test', balance=config.data_balance) # test_dataloader = DataLoader(test_data, batch_size=config.batch_size, shuffle=False, num_workers=config.num_workers) print('Test Image:', test_data.__len__()) # prepare model # model = ResNet34(num_classes=config.num_classes) # model = DenseNet121(num_classes=config.num_classes) # model = CheXPre_DenseNet121(num_classes=config.num_classes) # model = MultiResDenseNet121(num_classes=config.num_classes) # model = Vgg19(num_classes=config.num_classes) model = MultiResVgg19(num_classes=config.num_classes) if config.load_model_path: model.load(config.load_model_path) print('Model has been loaded!') else: print("Don't load model") if config.use_gpu: model.cuda() if config.parallel: model = torch.nn.DataParallel( model, device_ids=[x for x in range(config.num_of_gpu)]) model.eval() test_cm = meter.ConfusionMeter(config.num_classes) softmax = functional.softmax # go through the model for i, (image, label, image_path) in tqdm(enumerate(test_dataloader)): img = Variable(image, volatile=True) target = Variable(label) if config.use_gpu: img = img.cuda() target = target.cuda() score = model(img) test_cm.add(softmax(score, dim=1).data, target.data) SE, SP, ACC = calculate_index(test_cm.value()) print('confusion matrix:') print(test_cm.value()) print('Sensitivity:', SE) print('Specificity:', SP) print('test accuracy:', ACC)
def test( **kwargs ): # 注释掉LSTM_CRF.py里的_get_lstm_features函数里的self.hidden = self.init_hidden() config.parse(kwargs) # prepare data test_roots = [os.path.join(config.data_root, 'Features_Normal')] test_data = Feature_Dataset(test_roots, config.test_paths, phase='test') test_dataloader = DataLoader(test_data, batch_size=1, shuffle=False, num_workers=config.num_workers) print('Test Feature Lists:', test_data.__len__()) # prepare model model = BiLSTM_CRF(tag_to_ix=tag_to_ix, embedding_dim=EMBEDDING_DIM, hidden_dim=HIDDEN_DIM, num_layers=NUM_LAYERS) if config.load_model_path: model.load(config.load_model_path) if config.use_gpu: model.cuda() model.eval() # metric test_cm = [[0] * 3, [0] * 3, [0] * 3] # go through the model for i, (features, labels, feature_paths) in tqdm(enumerate(test_dataloader)): # prepare input target = torch.LongTensor([tag_to_ix[t[0]] for t in labels]) feat = Variable(features.squeeze()) # target = Variable(target) if config.use_gpu: feat = feat.cuda() # target = target.cuda() result = model(feat) # (score, predict list) for t, r in zip(target, result[1]): test_cm[t][r] += 1 SE, SP, ACC = calculate_index(test_cm) print('confusion matrix:') print(test_cm) print('Sensitivity:', SE) print('Specificity:', SP) print('test accuracy:', ACC)
def multitask_test(**kwargs): config.parse(kwargs) # prepare data test_data = MultiLabel_Dataset( config.data_root, config.test_paths, phase='test') # 注意这里不要加balance=False,否则生成的Dataset会包含混合型 test_dataloader = DataLoader(test_data, batch_size=config.batch_size, shuffle=False, num_workers=config.num_workers) print('Test Images:', test_data.__len__()) # prepare model model = MultiTask_DenseNet121(num_classes=2) # model = CheXPre_MultiTask_DenseNet121(num_classes=2) if config.load_model_path: model.load(config.load_model_path) if config.use_gpu: model.cuda() model.eval() test_cm_1 = meter.ConfusionMeter(2) test_cm_2 = meter.ConfusionMeter(2) test_cm_total = meter.ConfusionMeter(3) softmax = functional.softmax # misclassified = [] # go through the model for i, (image, label_1, label_2, label, image_path) in tqdm(enumerate(test_dataloader)): img = Variable(image, volatile=True) target_1 = Variable(label_1) target_2 = Variable(label_2) target = Variable(label) if config.use_gpu: img = img.cuda() target_1 = target_1.cuda() target_2 = target_2.cuda() target = target.cuda() # go through the model score_1, score_2 = model(img) p_1, p_2 = softmax(score_1, dim=1), softmax(score_2, dim=1) c = [] # ----------------------------------------------------------------------- for j in range(p_1.data.size()[0]): # 将两个支路合并得到最终的预测结果 if p_1.data[j][1] < 0.5 and p_2.data[j][1] < 0.5: c.append([1, 0, 0]) else: if p_1.data[j][1] > p_2.data[j][1]: c.append([0, 1, 0]) else: c.append([0, 0, 1]) # ----------------------------------------------------------------------- # misclassified image path # for path, predicted, true_label in zip(image_path, c, target): # if np.argmax(predicted, axis=0) != int(true_label): # misclassified.append((path, np.argmax(predicted, axis=0), int(true_label))) # misclassified.extend([(path, np.argmax(predicted, axis=0), int(true_label)) for path, predicted, true_label in zip(image_path, c, target) if np.argmax(predicted, axis=0) != int(true_label)]) test_cm_1.add(p_1.data, target_1.data) test_cm_2.add(p_2.data, target_2.data) test_cm_total.add(torch.FloatTensor(c), target.data) test_accuracy_1 = 100. * sum([test_cm_1.value()[c][c] for c in range(2) ]) / test_cm_1.value().sum() test_accuracy_2 = 100. * sum([test_cm_2.value()[c][c] for c in range(2) ]) / test_cm_2.value().sum() # test_accuracy_total = 100. * sum([test_cm_total.value()[c][c] for c in range(3)]) / test_cm_total.value().sum() SE, SP, ACC = calculate_index(test_cm_total.value()) print('test_cm_1:\n', test_cm_1.value(), '\ntest_cm_2:\n', test_cm_2.value(), '\ntest_cm_total:\n', test_cm_total.value()) print('test_accuracy_1:', test_accuracy_1, 'test_accuracy_2:', test_accuracy_2, 'test_accuracy_total:', ACC) print('total sensitivity:', SE) print('total specificity:', SP)
def label_based_3class(results_file): """ 以标注为基准定位病灶,计算准确率,混合型不加入统计。 """ def lesion_predict(dic): total = dic['0'] + dic['1'] + dic['2'] if dic['0'] / total > 0.7: re = 0 elif dic['1'] > dic['2']: re = 1 else: re = 2 return re with open(results_file, 'r') as f: results = f.readlines()[1:] lesions = lesion_localize(results, classes=3, changelabel=True) # 每个病灶的起始index,并且交换2和3的标签 # lesions.sort(key=lambda m: m[1]-m[0], reverse=False) print('total lesions:', len(lesions)) # pprint(lesions) result_dict = {'0': 0, '1': 0, '2': 0} cm = [[0, 0, 0], [0, 0, 0], [0, 0, 0]] for idx in tqdm(lesions): lesion_results = results[idx[0]:idx[1] + 1] # 这里要有+1,因为list截取一段不包含最后一个index # # 抛弃每段病灶的起始和结束的过渡部分 # length = idx[1]-idx[0]+1 # if length >= 10: # lesion_results = results[int(idx[0] + length*0.2): int(idx[1]+1 - length*0.2)] # elif 5 < length < 10: # lesion_results = results[idx[0]+1: idx[1]] # else: # lesion_results = results[idx[0]: idx[1]+1] lesion_label = idx[2] for x in lesion_results: predicted = int(x.strip().split(',')[1]) if predicted == 3: # 转换csv中预测的结果 predicted = 2 result_dict[str(predicted)] += 1 # print(idx, result_dict) lesion_predicted = lesion_predict(result_dict) if lesion_label != 3: # 对混合型不计入混淆矩阵 cm[lesion_label][lesion_predicted] += 1 result_dict = {'0': 0, '1': 0, '2': 0} SE, SP, ACC = calculate_index(cm) print(cm[0], '\n', cm[1], '\n', cm[2]) print('SE_0:', SE[0]) print('SE_1:', SE[1]) print('SE_2:', SE[2]) print('SP_0:', SP[0]) print('SP_1:', SP[1]) print('SP_2:', SP[2]) print('ACC:', ACC)
def predict_based_4class(results_file): """ 以预测的结果为基准定位病灶,计算准确率,统计混合型。 """ with open(results_file, 'r') as f: results = f.readlines()[1:] # ============================ Step1:将预测结果按照阈值和判断方法截断 ================================= len_threshold = 5 truncated_results = [] # 将读入的结果按照不同病人的id,是否超过长度阈值的判断方法截断,便于后续操作 temp = [] for i, x in enumerate(results): image_path = x.strip().split(',')[0] predict = int(x.strip().split(',')[1]) label = int(x.strip().split(',')[2]) prob_1 = x.strip().split(',')[3] prob_2 = x.strip().split(',')[4] prob_3 = x.strip().split(',')[5] if not temp: # 如果temp为空,即这是一段脊骨结果的第一张slice temp.append([image_path, predict, label, prob_1, prob_2, prob_3]) else: patient_id = image_path.split('/')[2] prepatient_id = results[i - 1].strip().split(',')[0].split('/')[2] if patient_id == prepatient_id: temp.append( [image_path, predict, label, prob_1, prob_2, prob_3]) else: # 如果当前slice的病人id和上一张不同,则应该从这里截断 if len(temp) >= len_threshold: # 对于本身长度就少于t的病灶直接舍弃 truncated_results.append(temp) # truncated_results.append(temp) temp = [[image_path, predict, label, prob_1, prob_2, prob_3]] # pprint(truncated_results[7]) # print(len(truncated_results[7])) # ============================ Step2:将单张预测结果以病灶为单位进行修正 ================================= processed_results = [] for res in tqdm(truncated_results): # 对于每一段截断脊骨,判断第一张的label for i, x in enumerate(res): if i + len_threshold <= len(res): res_next = [res[i + j][1] for j in range(len_threshold)] # print(res_next) # print([x[1]] * len_threshold) if res_next == [x[1]] * len_threshold: prepredict = x[1] break else: pass else: pass else: # 如果for循环里没有执行过break,即没有连续t个相同的slice,取这一段slice中数量最多的predict d = {'0': 0, '1': 0, '2': 0, '3': 0} for x in res: d[str(x[1])] += 1 prepredict = int( sorted(d.items(), key=lambda y: y[1], reverse=True)[0][0]) for i, x in enumerate(res): if x[1] == prepredict: # 如果当前slice的predict和上一张一致,则直接加入 processed_results.append(x[:3]) else: if i + len_threshold > len( res ): # 如果当前slice的predict和上一张不一致,但是剩余的slice数不足t张,则修改为和之前一致 processed_results.append([x[0], prepredict, x[2]]) else: res_next = [res[i + j][1] for j in range(len_threshold)] if res_next == [ x[1] ] * len_threshold: # 如果当前slice和predict和上一张不一致,且之后连续相同的超过t张,则直接加入并修改prepredict processed_results.append(x[:3]) prepredict = x[1] else: # 如果当前slice和predict和上一张不一致,且之后连续相同的不足t张,则修改为和之前一致 processed_results.append([x[0], prepredict, x[2]]) write_csv('results/processed_results.csv', ['path', 'predict', 'label'], processed_results) # ============================== Step3:由单张结果得到病灶结果并统计指标 ==================================== with open('results/processed_results.csv', 'r') as f: processed_results = f.readlines()[1:] predict_lesions = predict_lesion_localize(processed_results, classes=4) label_lesions = lesion_localize(processed_results, classes=4, changelabel=False) # pprint(lesions[:10]) # pprint(label_lesions[:10]) IOU_threshold = 0.5 cm = [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]] for preles in tqdm(predict_lesions): prestart, preend, predict = preles[0], preles[1], preles[2] pre_slice_index = [x for x in range(prestart, preend + 1)] label_slice_index = {'0': [], '1': [], '2': [], '3': []} for lables in label_lesions: labstart, labend, label = lables[0], lables[1], lables[2] if prestart > labend or preend < labstart: # 如果无交集 pass else: # print(labstart, labend, prestart, preend) for x in range(labstart, labend + 1): label_slice_index[str(label)].append(x) # print(len(label_slice_index['0'])) IOU = [ len(set(pre_slice_index) & set(label_slice_index['0'])) / len(set(pre_slice_index) | set(label_slice_index['0'])), len(set(pre_slice_index) & set(label_slice_index['1'])) / len(set(pre_slice_index) | set(label_slice_index['1'])), len(set(pre_slice_index) & set(label_slice_index['2'])) / len(set(pre_slice_index) | set(label_slice_index['2'])), len(set(pre_slice_index) & set(label_slice_index['3'])) / len(set(pre_slice_index) | set(label_slice_index['3'])) ] # print(set(pre_slice_index)) # print(set(label_slice_index['0'])) # print(len(set(pre_slice_index) & set(label_slice_index['0']))) # print("====================") # true_label = int(np.argmax(IOU[1:])) + 1 # 如果三类病中IOU最大的超过阈值则以此为label,否则label为0 # if IOU[true_label] < IOU_threshold: # true_label = 0 if IOU[predict] > IOU_threshold: true_label = predict else: true_label = int(np.argmax(IOU)) cm[true_label][predict] += 1 SE, SP, ACC = calculate_index(cm) print('confusion matrix') print(cm[0], '\n', cm[1], '\n', cm[2], '\n', cm[3]) print('SE_1:', SE[1]) print('SE_2:', SE[2]) print('SE_3:', SE[3]) print('SP_1:', SP[1]) print('SP_2:', SP[2]) print('SP_3:', SP[3]) print('ACC:', ACC)
def label_based_4class(results_file): """ 以标注为基准定位病灶,计算准确率,统计混合型。 """ def lesion_predict(dic): total = dic['0'] + dic['1'] + dic['2'] pos_total = dic['1'] + dic['2'] if dic['0'] / total > 0.7: re = 0 elif dic['1'] / pos_total > 0.7: re = 1 elif dic['2'] / pos_total > 0.7: re = 3 else: re = 2 # 当成骨和溶骨占比均小于0.7时记为混合型 return re with open(results_file, 'r') as f: results = f.readlines()[1:] lesions = lesion_localize(results, classes=4, changelabel=False) # 每个病灶的起始index # lesions.sort(key=lambda m: m[1]-m[0], reverse=False) print('total lesions:', len(lesions)) # pprint(lesions) result_dict = {'0': 0, '1': 0, '2': 0} cm = [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]] for idx in tqdm(lesions): lesion_results = results[idx[0]:idx[1] + 1] # 这里要有+1,因为list截取一段不包含最后一个index # # 抛弃每段病灶的起始和结束的过度部分 # length = idx[1]-idx[0]+1 # if length >= 10: # lesion_results = results[int(idx[0] + length*0.2): int(idx[1]+1 - length*0.2)] # elif 5 < length < 10: # lesion_results = results[idx[0]+1: idx[1]] # else: # lesion_results = results[idx[0]: idx[1]+1] lesion_label = idx[2] for x in lesion_results: predicted = int(x.strip().split(',')[1]) if predicted == 3: # 转换csv中预测的label predicted = 2 result_dict[str(predicted)] += 1 # print(idx, result_dict) lesion_predicted = lesion_predict(result_dict) cm[lesion_label][lesion_predicted] += 1 result_dict = {'0': 0, '1': 0, '2': 0} print(cm[0], '\n', cm[1], '\n', cm[2], '\n', cm[3]) print((cm[0][0] + cm[1][1] + cm[2][2] + cm[3][3]) / np.sum(cm)) SE, SP, ACC = calculate_index(cm) print(cm[0], '\n', cm[1], '\n', cm[2]) print('SE_1:', SE[1]) print('SE_2:', SE[2]) print('SE_3:', SE[3]) print('SP_1:', SP[1]) print('SP_2:', SP[2]) print('SP_3:', SP[3]) print('ACC:', ACC)