pytorch:对小鼠的脑电数据进行睡眠状态三分类


本文采用PyTorch框架,用实验室采集到老鼠大脑数据来学习一波多分类。

1.特征提取

我的数据是26只老鼠的mat形式的脑电数据,每个老鼠有15个通道,每个老鼠在不同的睡眠状态截取30段数据,每一段数据长为10s。 这里采集的睡眠状态有三种,分别是awake,rem,和sws
在这里插入图片描述

这里为了更好的获取时域和频域的特征,分别用相关矩阵和转移熵矩阵作为我们分类的特征,然后用pca方法对相关矩阵和转移熵矩阵各提取前30个特征,总共得到60个特征,最终得到的数据为(2340,60)的矩阵,接下来就可以开始处理了。

2.用pytorch分类

首先分出训练集和测试集

data_size = np.shape(all_sample)[0]
feature_size = np.shape(all_sample)[1]
n = int(data_size / 3) # 每个睡眠状态的样本数
X = all_sample
Y = np.zeros(data_size) # 为每个样本打label
Y[n:2 * n] = 1
Y[2 * n:] = 2
# 用sklearn里面的MinMaxScaler进行归一化
scaler_minmax = MinMaxScaler(feature_range=(-1, 1))  # 设置变换范围
X_minmax = scaler_minmax.fit_transform(X)
# 随机选取30%的数据作为测试集
X_train, X_test, Y_train, Y_test = train_test_split(X_minmax, Y, test_size=0.3)
# 样本数据转tensor float32
# label 转tensor int64
X_train = torch.from_numpy(X_train).to(torch.float).to(device)
X_test = torch.from_numpy(X_test).to(torch.float).to(device)
Y_train = torch.from_numpy(Y_train).to(torch.int64).to(device)
Y_test = torch.from_numpy(Y_test).to(torch.int64).to(device)

构建数据迭代器

pytorch 的迭代器可以很方便分批导入batch块,我们这里设置batch_size为30.

batch_size = 30
train_dataset = torch.utils.data.TensorDataset(X_train, Y_train)
test_dataset = torch.utils.data.TensorDataset(X_test, Y_test)
train_iter = torch.utils.data.DataLoader(train_dataset, batch_size=batch_size, shuffle=True, num_workers=0)
test_iter = torch.utils.data.DataLoader(test_dataset, batch_size=batch_size, shuffle=False, num_workers=0)

构建网络

用nn.Swquential()函数来构建网络。因为我们用到的神经网络中每一层之前都是全连接,所以可以用线性层加激活函数层来进行正向传播。隐藏层神经元个数设置为20,激活函数直接调用了nn里面的sigmoid函数(ReLU也可以,并且训练速度会快很多)。pytorch中的初始化可以用torch.nn中的init.normal_()函数直接对我们构建的net进行初始化。

# 模型构建
num_inputs, num_outputs, num_hiddens = feature_size, 3, 20
net = nn.Sequential(
    nn.Linear(num_inputs, num_hiddens),
    nn.Sigmoid(),
    # nn.Linear(num_hiddens, num_hiddens),
    # nn.ReLU(),
    nn.Linear(num_hiddens, num_outputs)
    # torch交叉熵的损失函数自带softmax运算,这里就没有再加一层激活函数
)

# 参数初始化
for param in net.parameters():
    init.normal_(param, mean=0, std=0.01)

准确率评估

训练完成后需要对测试集进行评估,我们先构建一个评估函数.这里模型的输出net(x)的形状是(batch_size, 3),所以判断输出结果时,用.argmax(dim=1)返回第二维的最大值的index。然后用.item()提取结算结果。

def acc(test_iter, net, device):
    acc_sum, n = 0.0, 0
    for x, y in test_iter:
        acc_sum += (net(x.to(device)).argmax(dim=1) == y.to(device)).sum().item()
        n += y.shape[0]
    return acc_sum / n

用该评估器来评估还未训练的模型对测试集的识别率,输出结果应该分布在1/3左右:

acc(test_iter, net, device)
Out[3]: 0.31196581196581197

模型训练

损失函数使用torch中的交叉熵损失函数

# 交叉熵损失函数
loss = torch.nn.CrossEntropyLoss()

优化器采用torch.optim中的SGD方法(Adam使用方法也类似),这里设置学习率为0.01,正则化参数为0.0001

# 优化器
optimizer = torch.optim.SGD(params=net.parameters(), lr=0.01, weight_decay=0.0001)
#optimizer = torch.optim.Adam(params=net.parameters(), lr=0.01, weight_decay=0.0001)

接下来开始训练,在pytorch中梯度的计算十分方便,我们可以直接在创建tensor时用requires_grad=True来设置是否跟踪梯度,在每个batch中只需用.backward()函数就可获得梯度,然后用optimizer.step()自动更新net中的参数。具体代码如下

num_epochs = 500
for epoch in range(num_epochs):
    train_l_sum, train_acc_sum, n = 0.0, 0.0, 0
    for x, y in train_iter:
        y_hat = net(x)
        l = loss(y_hat, y).sum()
        optimizer.zero_grad()  # 优化器的梯度清零
        l.backward()  # 反向传播梯度计算
        optimizer.step()  # 优化器迭代
        train_l_sum += l.item()
        train_acc_sum += (y_hat.argmax(dim=1) == y).sum().item()
        n += y.shape[0]
    test_acc = acc(test_iter, net, device)
    print('epoch %d, loss %.4f, train acc %.3f, test acc %.3f'
          % (epoch + 1, batch_size * train_l_sum / n, train_acc_sum / n, test_acc))

3. 分类结果

最终可以得到97%左右的正确率
在这里插入图片描述

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值