利用全连接网络实现病例AD,heart,WDBC等数据集的分类预测

1.网络搭建:

"""
作者:lds
网络搭建
"""
import torch.nn as nn
from torchvision import transforms as T
​
class Net(nn.Module):
    # 搭建6层网络
    def __init__(self, input, hidden_1, hidden_2, hidden_3, hidden_4, hidden_5,output):##在用到Net时,可以自己手动根据不同的数据集进行改动各层的大小。
        # nn.Module子类的函数必须在构造函数中执行父类的构造函数
        super(Net, self).__init__()
##充分利用Sequential函数,将线性层Linear、BatchNormalization和激活函数层Tanh()连接起来,从而构造一层全连接。
        self.hidden_layer1 = nn.Sequential(
            nn.Linear(input, hidden_1), nn.BatchNorm1d(hidden_1),
            nn.Tanh()
        )
        self.hidden_layer2 = nn.Sequential(
            nn.Linear(hidden_1, hidden_2), nn.BatchNorm1d(hidden_2),
            nn.Tanh()
        )
        self.hidden_layer3 = nn.Sequential(
            nn.Linear(hidden_2, hidden_3), nn.BatchNorm1d(hidden_3),
            nn.Tanh()
        )
        self.hidden_layer4 = nn.Sequential(
            nn.Linear(hidden_3, hidden_4), nn.BatchNorm1d(hidden_4),
            nn.Tanh()
        )
        self.hidden_layer5 = nn.Sequential(
            nn.Linear(hidden_4, hidden_5), nn.BatchNorm1d(hidden_5),
            nn.Tanh()
        )
        self.output_layer = nn.Sequential(
            nn.Linear(hidden_5, output),
            nn.Sigmoid()
        )
​
    def forward(self, x):
        x = self.hidden_layer1(x)
        x = self.hidden_layer2(x)
        x = self.hidden_layer3(x)
        x = self.hidden_layer4(x)
        x = self.hidden_layer5(x)
        x = self.output_layer(x)
​
        return x
​
​

2.网络参数配置:

"""
作者:lds
整个实验运行时涉及的一些自定义方法
包括数据获取、网络初始化、网络训练、网络测试以及交叉验证
"""
import pandas as pd
import numpy as np
import Visualization as v
import time
import torch as t
import torch.nn as nn
import scipy.io
import net as classifier
import torch.optim as opt
​
​
def init(model):
    """
    训练前对模型权重进行初始化
    :param model: 训练模型
    """
    for m in model.modules():
        if isinstance(m, nn.Linear):
            nn.init.xavier_uniform_(m.weight)  ##这里调用xavier_uniform初始化函数
​
​
def train(train_ds, train_ls, model, criterion, optimizer, epochs=20):
    """
    训练模型
    :param train_ds: 训练数据
    :param train_ls: 训练标签
    :param model: 训练模型
    :param criterion: 损失函数
    :param optimizer: 优化算法
    :param epochs: 迭代次数
    :return: 训练损失值
    """
    t_loss_list = []
    train_correct = 0
    # 将训练集迁移到GPU上
    train_ds = train_ds.cuda()
    train_ls = train_ls.cuda()
    model = model.cuda()
    init(model)
    for epoch in range(epochs-1):
        model.train()
        # 每次训练前梯度置零
        optimizer.zero_grad()
        # 正向传播
        output = model(train_ds)
        # 计算损失值
        train_loss = criterion(output, train_ls.squeeze())
        # 反向传播,计算梯度
        train_loss.backward()
        # 更新参数
        optimizer.step()
        t_loss_list.append(train_loss.item())
    # 获取预测值
    predict = output.max(1, keepdim=True)[1]
    # 统计预测正确个数
    train_correct += predict.eq(train_ls.view_as(predict)).sum().item()
​
    # 计算准确率
    train_accuracy = train_correct / train_ds.shape[0]
​
​
    print("Train loss: {:.3f}".format(train_loss.item()))
    print("Train Accuracy:{:.2f}%".format(train_accuracy*100))
​
    return train_loss.item(), train_accuracy, t_loss_list
​
​
def for_test(test_ds, test_ls, model, criterion):
    """
    测试模型
    :param test_ds: 测试数据
    :param test_ls: 测试标签
    :param model: 测试模型
    :param criterion: 损失函数
    :return: 测试损失值,测试准确度
    """
    # 将测试数据迁移到GPU上
    test_ds = test_ds.cuda()
    test_ls = test_ls.cuda()
    model = model.eval()
    correct = 0
​
    with t.no_grad():
        # 使用训练好的模型测试
        output = model(test_ds)
        # 计算测试集损失函数
        test_loss = criterion(output, test_ls.squeeze())
        # 获取预测值
        predict = output.max(1, keepdim=True)[1]
        # 统计预测正确个数
        correct += predict.eq(test_ls.view_as(predict)).sum().item()
​
        # 计算准确率
        accuracy = correct / test_ds.shape[0]
​
    print("Test loss: {:.3f}".format(test_loss.item()))
    print("Test Accuracy:{:.2f}%".format(accuracy*100))
​
    return test_loss.item(), accuracy
​
​
def train_va(dataname, c_model, c_epochs, c_criterion, c_opt, result_name):   ###k, c_datas, c_labels,
    """
    对模型进行训练和可视化
    :param dataname: 数据集的名字
    :param c_datas: 数据集
    :param c_labels: 标签集
    :param c_model: 用于分类的模型
    :param c_epochs: 迭代次数
    :param c_criterion: 损失函数
    :param c_opt: 优化算法
    :param result_name: 实验结果文件名字符串
    """
    # 获取样本总数
    # examples = c_datas.shape[0]
    # # 每一份有几个样本
    # batch_examples = examples // k
​
    # 存储每次验证结果
    performs = []
​
    # 存储训练损失值、准确率,测试损失值、准确率,用于可视化和计算最终结果
    t_loss_list = []
    t_acc_list = []
    v_loss_list = []
    v_acc_list = []
​
    # 记录整个训练起始时间
    start_time = time.perf_counter()
    #划分相应的数据集
    data = scipy.io.loadmat('%s.mat'%(dataname))
    # data=data.to_numpy()
    train_datas = data['xtrain']
    train_labels = data['ytrain']
    test_datas = data['xtest']
    test_labels = data['ytest']
    # 固定随机种子,确保每次运行结果一致
    np.random.seed(5)
    # 判断标签是否符合标准,即是否从0开始标注
    if 0 not in train_labels:
        # 标签从1开始,就将每个标签值-1
        train_labels = train_labels - 1
    if 0 not in test_labels:
        # 标签从1开始,就将每个标签值-1
        test_labels = test_labels - 1
    train_datas = train_datas / 1.0
    train_datas =t.from_numpy(train_datas).float()
    train_labels = t.from_numpy(train_labels).long()
    test_datas = test_datas / 1.0
    test_datas = t.from_numpy(test_datas).float()
    test_labels = t.from_numpy(test_labels).long()
​
    # for i in range(c_epochs):
    t_loss, t_acc , t_loss_list= train(train_datas, train_labels, c_model, c_criterion, c_opt, epochs=c_epochs)    # 测试
    v_loss, v_acc = for_test(test_datas, test_labels, c_model, c_criterion)
    # 清空cuda缓存
    t.cuda.empty_cache()
    # 将该次训练损失值和测试准确度存放到列表中
    performs.append((v_acc, v_loss))
​
    t_loss_list.append(t_loss)
    v_loss_list.append(v_loss)
    print(v_loss_list)
​
    # 记录整个训练结束时间
    end_time = time.perf_counter()
​
    #根据准确度从小到大排序
    performs = sorted(performs)
    # 打印最高准确度
    print("loss: {:.3f}, accuracy: {:.2f}%".format(performs[-1][1], performs[-1][0] * 100))
    v_acc_list.append(performs[-1][0] * 100)
    # 打印耗时
    print("共耗时:{:.3f} s".format(end_time - start_time))
    # 可视化模型性能
    v.visualization(dataname, t_loss_list, result_name, v_acc_list)
​
###test结果
# if __name__ == '__main__':
#     DATAFILE1 = "data\\heart.mat"
#     classifer2 = classifier.Net(13, 104, 52, 26, 13, 8, 2)   ##对应于AD数据集的模型
#     optimizer = opt.Adam(classifer2.parameters(), lr=0.01, betas=(0.9, 0.99))
#     criterion = nn.CrossEntropyLoss()
#     picture_name = DATAFILE1.split("\\")[-1].split(".")[0] + "_result"
#     dataname = DATAFILE1.split("\\")[-1].split(".")[0]
#     cross_validation(dataname, classifer2, 200, criterion, optimizer, picture_name)
​

3.可视化:

"""
对实验的结果可视化
作者:lds
"""
import matplotlib.pyplot as plt
plt.rc("font", family='KaiTi')
EPOCHS = 600
​
import matplotlib.pyplot as plt
​
​
def visualization(dataname, t_loss_list, result_name, v_acc_list):
    # plt.ion()
    plt.figure()
    f, axes = plt.subplots(1, 1)
    # ax0 = axes[0, 0]
​
​
    if dataname=='AD':
        axes.clear()
        axes.plot([x for x in range(EPOCHS)], t_loss_list)  ###range(1,11)
        axes.set_xlabel("训练轮次")
        axes.set_ylabel("损失值")
        axes.set_title("AD")
        axes.set_ylim((0.5, max(t_loss_list)))  ###1
        axes.set_xlim((1, EPOCHS))
​
        row_labels = ['准确率:']
        col_labels = ['数值']
        value = v_acc_list[0]
        table_vals = [['{:.2f}%'.format(value)]]
        row_colors = ['gold']
        my_table = plt.table(cellText=table_vals, colWidths=[0.1] * 5,
                             rowLabels=row_labels, rowColours=row_colors, loc='best')
        plt.savefig(result_name + ".png")
        plt.show()
​
    if dataname == 'heart':
        axes.clear()
        axes.plot([x for x in range(EPOCHS)], t_loss_list)  ###range(1,11)
        axes.set_xlabel("训练轮次")
        axes.set_ylabel("损失值")
        axes.set_title("heart")
        axes.set_ylim((0.35, max(t_loss_list)))  ###1
        axes.set_xlim((1, EPOCHS))
        row_labels = ['准确率:']
        col_labels = ['数值']
        value = v_acc_list[0]
        table_vals = [['{:.2f}%'.format(value)]]
        row_colors = ['gold']
        my_table = plt.table(cellText=table_vals, colWidths=[0.1] * 5,
                             rowLabels=row_labels, rowColours=row_colors, loc='best')
        plt.savefig(result_name + ".png")
        plt.show()
    if dataname == 'maxLittle':
        axes.clear()
        axes.plot([x for x in range(EPOCHS)], t_loss_list)  ###range(1,11)
        axes.set_xlabel("训练轮次")
        axes.set_ylabel("损失值")
        axes.set_title("maxLittle")
        axes.set_ylim((0.35, max(t_loss_list)))  ###1
        axes.set_xlim((1, EPOCHS))
        row_labels = ['准确率:']
        col_labels = ['数值']
        value = v_acc_list[0]
        table_vals = [['{:.2f}%'.format(value)]]
        row_colors = ['gold']
        my_table = plt.table(cellText=table_vals, colWidths=[0.1] * 5,
                             rowLabels=row_labels, rowColours=row_colors, loc='best')
        plt.savefig(result_name + ".png")
        plt.show()
    if dataname == 'PD':
        axes.clear()
        axes.plot([x for x in range(EPOCHS)], t_loss_list)  ###range(1,11)
        axes.set_xlabel("训练轮次")
        axes.set_ylabel("损失值")
        axes.set_title("PD")
        axes.set_ylim((0.3, max(t_loss_list)))  ###1
        axes.set_xlim((1, EPOCHS))
        row_labels = ['准确率:']
        col_labels = ['数值']
        value = v_acc_list[0]
        table_vals = [['{:.2f}%'.format(value)]]
        row_colors = ['gold']
        my_table = plt.table(cellText=table_vals, colWidths=[0.1] * 5,
                             rowLabels=row_labels, rowColours=row_colors, loc='best')
        plt.savefig(result_name + ".png")
        plt.show()
    if dataname == 'pima-indians-diabetes':
        axes.clear()
        axes.plot([x for x in range(EPOCHS)], t_loss_list)  ###range(1,11)
        axes.set_xlabel("训练轮次")
        axes.set_ylabel("损失值")
        axes.set_title("pima-indians-diabetes")
        axes.set_ylim((0.6, max(t_loss_list)))  ###1
        axes.set_xlim((1, EPOCHS))
        row_labels = ['准确率:']
        col_labels = ['数值']
        value = v_acc_list[0]
        table_vals = [['{:.2f}%'.format(value)]]
        row_colors = ['gold']
        my_table = plt.table(cellText=table_vals, colWidths=[0.1] * 5,
                             rowLabels=row_labels, rowColours=row_colors, loc='best')
        plt.savefig(result_name + ".png")
        plt.show()
    if dataname == 'vehicle':
        axes.clear()
        axes.plot([x for x in range(EPOCHS)], t_loss_list)  ###range(1,11)
        axes.set_xlabel("训练轮次")
        axes.set_ylabel("损失值")
        axes.set_title("vehicle")
        axes.set_ylim((0.7, max(t_loss_list)))  ###1
        axes.set_xlim((1, EPOCHS))
        row_labels = ['准确率:']
        col_labels = ['数值']
        value = v_acc_list[0]
        table_vals = [['{:.2f}%'.format(value)]]
        row_colors = ['gold']
        my_table = plt.table(cellText=table_vals, colWidths=[0.1] * 5,
                             rowLabels=row_labels, rowColours=row_colors, loc='best')
        plt.savefig(result_name + ".png")
        plt.show()
    if dataname == 'WDBC':
        axes.clear()
        axes.plot([x for x in range(EPOCHS)], t_loss_list)  ###range(1,11)
        axes.set_xlabel("训练轮次")
        axes.set_ylabel("损失值")
        axes.set_title("WDBC")
        axes.set_ylim((0.1, max(t_loss_list)))  ###1
        axes.set_xlim((1, EPOCHS))
        row_labels = ['准确率:']
        col_labels = ['数值']
        value = v_acc_list[0]
        table_vals = [['{:.2f}%'.format(value)]]
        row_colors = ['gold']
        my_table = plt.table(cellText=table_vals, colWidths=[0.1] * 5,
                             rowLabels=row_labels, rowColours=row_colors, loc='best')
        plt.savefig(result_name + ".png")
        plt.show()
    if dataname == 'Wisconsin':
        axes.clear()
        axes.plot([x for x in range(EPOCHS)], t_loss_list)  ###range(1,11)
        axes.set_xlabel("训练轮次")
        axes.set_ylabel("损失值")
        axes.set_title("Wisconsin")
        axes.set_ylim((1, max(t_loss_list)))  ###1
        axes.set_xlim((1, EPOCHS))
        row_labels = ['准确率:']
        col_labels = ['数值']
        value = v_acc_list[0]
        table_vals = [['{:.2f}%'.format(value)]]
        row_colors = ['gold']
        my_table = plt.table(cellText=table_vals, colWidths=[0.1] * 5,
                             rowLabels=row_labels, rowColours=row_colors, loc='best')
        plt.savefig(result_name + ".png")
        plt.show()
​
​
    plt.tight_layout()  # 自动布局子图
​

4.主函数:

''''
作者:lds
''''
import utils as f
import net as classifier
import torch.nn as nn
import torch.optim as opt
​
DATAFILE1 = "data\\AD.mat"                    # 各个数据集的路径
DATAFILE2 = "data\\heart.mat"
DATAFILE3 = "data\\maxLittle.mat"
DATAFILE4 = "data\\PD.mat"
DATAFILE5 = "data\\pima-indians-diabetes.mat"
DATAFILE6 = "data\\vehicle.mat"
DATAFILE7 = "data\\WDBC.mat"
DATAFILE8 = "data\\Wisconsin.mat"
EPOCHS = 600                             # 迭代次数
​
​
def start(datafile, model, lr):
    print("Starting")
    print("Loading datas...")
    # 获取数据集和标签集
    # datas, labels = f.get_datas(datafile)
    print("Datas Loaded!")
# 定义损失函数,使用交叉熵损失函数
    criterion = nn.CrossEntropyLoss()
    # 定义优化算法,使用Adam算法,学习率lr为0.005,β1=0.9,β2=0.99
    optimizer = opt.Adam(model.parameters(), lr=lr, betas=(0.9, 0.99))
    print("Training and Validating...")
    # 根据数据集路径生成结果图的文件名
    picture_name = datafile.split("\\")[-1].split(".")[0] + "_result"
    dataname = datafile.split("\\")[-1].split(".")[0]
    f.train_va(dataname, model, EPOCHS, criterion, optimizer, picture_name)
​
​
if __name__ == '__main__':
    # 创建分类器
    classifer1 = classifier.Net(32, 256, 128, 64, 32, 12, 3)  ##对应于AD数据集的模型
    classifer2 = classifier.Net(13, 208, 104, 52, 26, 13, 2)   ##对应于heart数据集的模型
    classifer3 = classifier.Net(22, 176, 88, 44, 11, 8, 2)   ##对应于maxLittle数据集的模型
    classifer4 = classifier.Net(26, 208, 104, 52, 26, 13, 2)   ##对应于PD数据集的模型
    classifer5 = classifier.Net(8, 64, 32, 16, 8, 4, 2)      ##对应于pima-indians-diabetes数据集的模型
    classifer6 = classifier.Net(18, 144, 72, 36, 18, 8, 4)   ##对应于vehicle数据集的模型
    classifer7 = classifier.Net(30, 240, 120, 60, 30, 10, 2)  ##对应于WDBC数据集的模型
    classifer8 = classifier.Net(9, 72, 36, 18, 9, 6, 4)      ##对应于Wisconsin数据集的模型
​
​
    print("------ 对AD数据集进行训练 -----")
    start(DATAFILE1, classifer1, 0.00005)
​
    print("\n------ 对heart数据集进行训练 -----")
    start(DATAFILE2, classifer2, 0.0001)
​
    print("\n------ 对maxLittle数据集进行训练 -----")
    start(DATAFILE3, classifer3, 0.0005)
​
    print("\n------ 对PD数据集进行训练 -----")
    start(DATAFILE4, classifer4, 0.0005)
​
    print("\n------ 对pima-inidians-diabetes数据集进行训练 -----")
    start(DATAFILE5, classifer5, 0.0005)
​
    print("\n------ 对vehicle数据集进行训练 -----")
    start(DATAFILE6, classifer6, 0.0005)
​
    print("\n------ 对WDBC数据集进行训练 -----")
    start(DATAFILE7, classifer7, 0.0005)
​
    print("\n------ 对Wisconsin数据集进行训练 -----")
    start(DATAFILE8, classifer8, 0.0005)
​
​
​
​

5.结果展示:(以下是对AD,heart,WDBC等数据集的分类预测)

利用全连接网络实现病例AD,heart,WDBC等数据集的分类预测

利用全连接网络实现病例AD,heart,WDBC等数据集的分类预测

利用全连接网络实现病例AD,heart,WDBC等数据集的分类预测

利用全连接网络实现病例AD,heart,WDBC等数据集的分类预测

利用全连接网络实现病例AD,heart,WDBC等数据集的分类预测

利用全连接网络实现病例AD,heart,WDBC等数据集的分类预测

利用全连接网络实现病例AD,heart,WDBC等数据集的分类预测

上一篇:某些函数与知识点的复习


下一篇:Repulsion loss:专注于遮挡情况下的行人检测