pytorch 對小鼠的腦電資料進行睡眠狀態三分類

2021-10-08 23:31:03 字數 4534 閱讀 6602

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 一部分用於訓練,一部分用於測試...