pytorch搭建卷积神经网络cnn处理脑电数据过程代码

16 篇文章 5 订阅
12 篇文章 2 订阅

参考图像处理的代码,自己对脑电数据进行了应用,数据量比较小,准确率不高,主要为了理解算法结构。

参考文章:https://zhuanlan.zhihu.com/p/115866586

谢谢大佬的分享,代码很清晰,便于理解,但是下载后还是不能直接在我的脑电数据中运行进行处理,主要是数据结构和数据类型不同,需要手动再进行调整。

原文中是对minitst数据进行了图像的分类,训练数据是四维的,有10个标签,脑电数据这里用的三维,并且维度中的数据长度也有影响,所以一定需要对网络结构进行调整,可以两篇文章中的代码对比阅读,更有利于对维度的变化,结构的调整进行理解。

我的脑电是用Matlab采集的,16维的数据和标签保存在结构体数据中,所以在代码的最开始还对数据进行了手动分段

整个代码分为几个部分:准备数据,搭建神经网络,训练数据,预测数据

1.导入包

#导入包
import torch
torch.set_default_tensor_type(torch.FloatTensor)
import numpy as np
import scipy.io
import torch.utils.data as Data
import torch.nn as nn
import torch.nn.functional as F

2.准备数据

#准备数据
# make data
## load eegdata
samplesfile = scipy.io.loadmat('/Users/thrive/Documents/Dong/research/mypaper/code/dataset/rawdata/subject1.mat') #读入字典
eegdata = samplesfile['eeg'] #提取numpy数组,结构体名称是eeg,包含字段有name date data1 marker1 data2 marker2……
print('# test eegdata:',eegdata[0,0]['marker1'][:2,:1],'\n')#打印出来marker1字段看一下

tbase=0.2#基线长度
ttrial=0.5#关注的脑电时间段
fs=1200#采样率

## train data
### epoch data将数据分段
epochdata=np.zeros((20,16,int((tbase+ttrial)*fs)))#初始化一个数组用于存放分段后的脑电数据

i=0
for temp in epochdata:
    epochdata[i,:,:]=eegdata[0,0]['data1'][:,round((eegdata[0,0]['marker1'][i,1]-tbase)*fs):round((eegdata[0,0]['marker1'][i,1]-tbase)*fs)+int((tbase+ttrial)*fs)]
    i+=1
epochdata=torch.FloatTensor(epochdata)#将分段后的数据转化为float类型,否则无法进行训练
print('# test shape of 3D data:',epochdata.shape,'\n')
print('# test epoched data:',epochdata[:2,2:3,:2],'\n')

### make labels做标签
labels=np.zeros((20))#初始化标签数组
labels=torch.LongTensor(eegdata[0,0]['marker1'][:,2])#标签需要转化为long类型,否则无法进行训练
print('# test labels shape:',labels.shape,'\n')
print('# test labels:',labels[0])

### make train data
batch_size = 20
traindataset = Data.TensorDataset(epochdata, labels)
train_loader = Data.DataLoader(traindataset, batch_size, shuffle=True)# 随机读取小批量
for X,y in train_loader:
    print(X,y)
    break

## test data 按照上边的方法准备测试集,但最后有些不同
epochdata=np.zeros((20,16,int((tbase+ttrial)*fs)))

i=0
for temp in epochdata:
    epochdata[i,:,:]=eegdata[0,0]['data2'][:,round((eegdata[0,0]['marker2'][i,1]-tbase)*fs):round((eegdata[0,0]['marker2'][i,1]-tbase)*fs)+int((tbase+ttrial)*fs)]
    i+=1
epochdata=torch.FloatTensor(epochdata)
print('# test shape of 3D data:',epochdata.shape,'\n')
print('# test epoched data:',epochdata[:2,2:3,:2],'\n')

### make labels
labels=np.zeros((20))
labels=torch.LongTensor(eegdata[0,0]['marker2'][:,2])
print('# test labels shape:',labels.shape,'\n')
print('# test labels:',labels[0])
#训练集中会自动进行归一化,测试集要手动归一化一哈(应该是在下边的代码中针对训练集和测试集的区别,所以需要这一步)
m=nn.LayerNorm([20,16,840])
test_x=m(epochdata)
test_y=labels

3.搭建网络结构

#定义网络
class CNN(nn.Module):
    def __init__(self):
        super(CNN,self).__init__()
        self.conv1 = nn.Sequential(
            nn.Conv1d(
                in_channels=16,
                out_channels=16,
                kernel_size=3,#卷积核3*3
                stride=1,#步长
                padding=1#边缘填充
            ),                               #维度变换(20,16,840) --> (20,16,840)
            nn.ReLU(),
            nn.MaxPool1d(kernel_size=2)      #维度变换(20,16,840) --> (20,16,420)
        )
        self.conv2 = nn.Sequential(
            nn.Conv1d(
                in_channels=16,
                out_channels=32,
                kernel_size=3,
                stride=1,
                padding=1
            ),                               #维度变换(20,16,420) --> (20,32,420)
            nn.ReLU(),
            nn.MaxPool1d(kernel_size=2)      #维度变换(20,32,420) --> (20,32,210)
        )
        self.output = nn.Linear(32*210,2)    #这里的32*210是数字,不代表二维32维度乘以210,训练数据有变化的时候,这里必须要改

    def forward(self, x):
        out = self.conv1(x)
        out = self.conv2(out)
        #out.view平铺到一维,类似于keras中的flatten
        out = out.view(out.size(0),-1)      #pytorch的展平操作是在forward中定义的,在这里维度变为二维20*(32*210)
        out = self.output(out)
        return out

cnn = CNN()
print(cnn)#打印查看网络结构

4.训练

#准备训练
optimizer = torch.optim.Adam(cnn.parameters(),lr=0.001,)#使用adam优化算法进行训练
loss_func = nn.CrossEntropyLoss()#损失函数选择交叉熵损失函数
for epoch in range(30):
    for step ,(b_x,b_y) in enumerate(train_loader):
        output = cnn(b_x)
        #b_y必须为long型
        loss = loss_func(output,b_y)

        optimizer.zero_grad()#梯度置零
        loss.backward()
        optimizer.step()#参数更新

        if step%20 ==0:
            test_output = cnn(test_x)
            #.max(a,1)返回a中每行的最大值,[1].data.numpy(),返回最大值的位置索引
            pred_y = torch.max(test_output, 1)[1].data.numpy()
            accuracy = float((pred_y == test_y.data.numpy()).astype(int).sum()) / float(test_y.size(0))
            print('Epoch: ', epoch, '| train loss: %.4f' % loss.data.numpy(), '| test accuracy: %.2f' % accuracy)
print('finish training')
torch.save(cnn,'cnn_minist.pkl')#保存训练好的网络

5.预测

#使用训练好的网络预测
cnn = torch.load('cnn_minist.pkl')

test_output = cnn(test_x[:20])
pred_y = torch.max(test_output, 1)[1].data.numpy()

print(pred_y, 'prediction number')
print(test_y[:20].numpy(), 'real number')

test_output1 = cnn(test_x)
pred_y1 = torch.max(test_output1, 1)[1].data.numpy()
accuracy = float((pred_y1 == test_y.data.numpy()).astype(int).sum()) / float(test_y.size(0))
print('accuracy',accuracy)

到此就结束了,因为我在这里用的脑电数据特别的少,只有20个分段,所以分类效果很差,和随机的50%一样,当然和数据质量以及网络结构也都有关系,不过就是为了理解结构,然后就可以自己增加数据量以及调整网络结构进行优化了。

这里暂时先不分享我采集到的数据,有机会的话,之后再说

  • 11
    点赞
  • 128
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 18
    评论
好的,以下是使用PyTorch搭建卷积神经网络(Convolutional Neural Network,简称CNN)识别手写数字的代码: ```python import torch import torch.nn as nn import torch.optim as optim import torchvision.transforms as transforms import torchvision.datasets as datasets # 定义CNN网络结构 class Net(nn.Module): def __init__(self): super(Net, self).__init__() self.conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1) self.conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1) self.pool = nn.MaxPool2d(2, 2) self.fc1 = nn.Linear(64 * 7 * 7, 128) self.fc2 = nn.Linear(128, 10) def forward(self, x): x = self.pool(torch.relu(self.conv1(x))) x = self.pool(torch.relu(self.conv2(x))) x = x.view(-1, 64 * 7 * 7) x = torch.relu(self.fc1(x)) x = self.fc2(x) return x # 加载数据集 transform = transforms.Compose( [transforms.ToTensor(), transforms.Normalize(mean=(0.5,), std=(0.5,))]) trainset = datasets.MNIST(root='./data', train=True, download=True, transform=transform) trainloader = torch.utils.data.DataLoader(trainset, batch_size=64, shuffle=True, num_workers=2) testset = datasets.MNIST(root='./data', train=False, download=True, transform=transform) testloader = torch.utils.data.DataLoader(testset, batch_size=64, shuffle=False, num_workers=2) # 训练CNN模型 net = Net() criterion = nn.CrossEntropyLoss() optimizer = optim.SGD(net.parameters(), lr=0.01, momentum=0.9) for epoch in range(10): running_loss = 0.0 for i, data in enumerate(trainloader, 0): inputs, labels = data optimizer.zero_grad() outputs = net(inputs) loss = criterion(outputs, labels) loss.backward() optimizer.step() running_loss += loss.item() if i % 100 == 99: # 每100个batch输出一次损失值 print('[%d, %5d] loss: %.3f' % (epoch + 1, i + 1, running_loss / 100)) running_loss = 0.0 print('Finished Training') # 测试CNN模型 correct = 0 total = 0 with torch.no_grad(): for data in testloader: images, labels = data outputs = net(images) _, predicted = torch.max(outputs.data, 1) total += labels.size(0) correct += (predicted == labels).sum().item() print('Accuracy of the network on the 10000 test images: %d %%' % ( 100 * correct / total)) ``` 这份代码中,首先定义了一个包含两个卷积层和两个全连接层的CNN网络结构。然后使用PyTorch内置的MNIST数据集加载器加载手写数字数据集,并进行了数据处理(将像素值归一化到-1到1之间)。接着使用随机梯度下降(SGD)算法训练CNN模型,最后在测试集上评估模型准确率。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 18
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

油泼西红柿

Wish U Thrive

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值