3. 分類結果
本文採用pytorch框架,用實驗室採集到老鼠大腦資料來學習一波多分類。
我的資料是26只老鼠的mat形式的腦電資料,每個老鼠有15個通道,每個老鼠在不同的睡眠狀態擷取30段資料,每一段資料長為10s。 這裡採集的睡眠狀態有三種,分別是awake,rem,和sws
這裡為了更好的獲取時域和頻域的特徵,分別用相關矩陣和轉移熵矩陣作為我們分類的特徵,然後用pca方法對相關矩陣和轉移熵矩陣各提取前30個特徵,總共得到60個特徵,最終得到的資料為(2340,60)的矩陣,接下來就可以開始處理了。
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 =
30train_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,
20net = 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,
0for 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 =
500for epoch in
range
(num_epochs)
: train_l_sum, train_acc_sum, n =
0.0,
0.0,
0for 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)
)
最終可以得到97%左右的正確率
主成分分析(PCA)對腦電資料進行降維
主成分分析是降維裡面常見的技術,它的求值是乙個解析解,並不需要進行迭代,其主成分可由原資料直接求得。本文不講原理,而是以乙個腦電波資料的例子進行展示,該腦電波資料分為正負兩個樣本集各52個樣本,每個樣本的維數為59維,全部放在乙個檔案裡面,其對應的標籤也放在乙個檔案裡面 見資料網盤鏈結 現對該腦電資...
腦電微狀態的時間結構
考慮到只有少數微狀態地形圖,並且它們在持續時間約為100 ms的離散塊中交替,因此有必要討論這種交替的時間結構是否遵循某些規則。主要問題不僅在於微觀狀態的轉變是否是非隨機的,而且在於這種非隨機性是否在不同的時間尺度上是可觀測的。之前針對過渡概率的幾項清楚地證明了這些概率是非隨機的,但是精神 症患者的...
腦電資料(EEG SEEG)處理 特徵視覺化
在之前的文章中,我已經介紹了利用cnn神經網路來進行腦電特徵的提取及識別。我的課題是有關癲癇的腦電特徵分析,在實際的實驗中你會發現,你的神經網路很容易過擬合,可以將實驗抽象為分類任務,可以分為兩個方向來進行訓練 將所有的資料劃按照一定的比例劃分為兩個部分 eg.7 3 一部分用於訓練,一部分用於測試...