利用LSTM對腦電波訊號進行分類

2021-09-01 12:47:55 字數 3420 閱讀 5817

最近我們在做利用lstm網路對腦電波訊號(紡錘體)進行分類的相關工作。我們的資料集是來自於美國開源的睡眠資料集(national sleep research resource)

我們獲得資料報含 紡錘波的持續時間,振幅,時間,等幾個特徵。我們採集的樣本主要來自於正常人和病人。我們初步的思想是將紡錘波視為乙個事件,生成乙個序列。出現紡錘波訊號的為1,反之為0.然後利用神經網路,來學習這個序列的內部特徵,通過序列來判斷病人有沒有患病。

眾所周知lstm神經網路在處理時序資訊時有乙個很好的效果,特別是幾年來nlp的飛速發展。

我們首先需要的是對序列進行二進位制編碼

def bit_coding(data, step): #對乙個資料進行編碼

code =

pre_data = 0

count = 0

length = len(data)

while count < length:

n = (data[count]-pre_data) / step

if n > 0:

if n % 1 > 0:

n = int(n)

code += [0] * n + [1]

else:

n = int(n)

code += [0] * (n - 1) + [1]

pre_data = data[count]

count += 1

return code

其中的step就是設定的精度,多少步長進行統計,這個值將決定你獲得乙個腦電波的序列的維度大小。

我們再生成乙個腦電波的類的相關資訊

class spindledata:

path = ""

paths =

labels =

data =

step = 0.0001

max_length = 0#設定預設的編碼間隔

coding_q =

def __init__(self, path="datasets", step=0.0001 ):

self.path = path

self.step =step

self.paths, self.labels = self.get_data_labels() #獲得路徑以及標籤

self.coding()

def get_data_labels(self): # 返回獲取的資料以及標籤[0,1,0,1,...] "./datasets/"

path = self.path

cate = [(os.path.join(path, x)) for x in os.listdir(path)]

paths =

labels =

for i, p in enumerate(cate):

path_tmps = glob.glob(os.path.join(p, "*.csv"))

for p in path_tmps:

np.asarray(labels) #將標籤轉化為np的格式

return paths, labels

def coding(self):#所有的資料讀取以及儲存(這裡儲存了資料的原始資料占用記憶體可能比較大)

codeing_q =

for p in self.paths:

data = pd.read_csv(p, skiprows=(0, 1), sep=",")

print("正在讀取第%d個csv檔案..." % (self.paths.index(p)+1))

data =data['time_of_night']

for i, d in enumerate(self.data):

code = bit_coding(d, step=self.step)

print("正在對第%d個序列進行編碼..."%(i+1))

self.max_length = max([len(x) for x in codeing_q])

codeing_q = preprocessing.sequence.pad_sequences(codeing_q, maxlen=self.max_length) #將所有的串都弄成相同的維度

self.coding_q = np.asarray(codeing_q)

這個類主要包含編碼後的0/1序列,1序列表示的是紡錘波出現,0表示的是紡錘波沒有出現。同時我們利用了keras 的對齊。超過固定長度的部分會被截斷,不足的部分會補零。同時我們再生成乙個labels陣列,這個對應的是病人患病與健康。其實就是乙個二分類問題。

我們再來搭建乙個lstm神經網路

def learning_lstm():                   #lstm暫時還是比較適合於文字中,對於有序序暫不合適

x_train, y_labels, length = data_test()

x_train = np.expand_dims(x_train, axis=2)

model = sequential()

# model.add(embedding(max_feature, 32))

model.add(lstm(32, input_shape=(length, 1)))

model.add(dense(1, activation='sigmoid'))

model.compile(optimizer='rmsprop', loss='binary_crossentropy', metrics=['acc'])

model.summary()

history = model.fit(x_train, y_labels, epochs=10, batch_size=16, validation_split=0.2)

draw(history)

def data_test():

length = 0 #每乙個系列的長度

spindle = spindledata()

x_train = spindle.coding_q

y_train = spindle.labels

length = spindle.max_length

return x_train, y_train, length

我實驗中的step設定的最小間距0.0001,因此每個序列都有120,000維.暫時實驗的效果不是很明顯。

由於我們暫時獲取的資料還比較小,導致訓練不充分,同時可能會導致過擬合等問題。接下來我們會進行改進測試。

我先把github原始碼發上來,相關的原發發布到了我的github上: 歡迎指正!

腦電溯源定位

頭皮記錄的腦電是大腦中很多源在記錄點疊加起來的結果,而且,這些源的方向 一般隨著皮層的褶皺而變化 對最後測量出來的頭皮腦電有很大影響。所以不能簡單的把頭皮對應的啟用位置對映到皮層上去,那就只有借助於溯源方法了。所謂腦電溯源定位,也即腦電逆向問題,概括的說就是 根據頭表測量電位訊號,反演估計腦內神經活...

腦電電極帽

本文首發在個人部落格上 7988888.xyz 好了,上面說的這些是我最近遇到的問題,進入到今天分享的主題吧,今天要談到的是我們目前所使用到的電極帽種類,總體來說一共分為兩個大的種類 溼電極帽和幹電極帽 電極帽在eeg資料實驗中重要嗎?重要的,電極帽上一般都帶有電極感測器,通過在電極感測器與頭皮之間...

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

3.分類結果 本文採用pytorch框架,用實驗室採集到老鼠大腦資料來學習一波多分類。我的資料是26只老鼠的mat形式的腦電資料,每個老鼠有15個通道,每個老鼠在不同的睡眠狀態擷取30段資料,每一段資料長為10s。這裡採集的睡眠狀態有三種,分別是awake,rem,和sws 這裡為了更好的獲取時域和...