2016-09-17 38 views
0

我對fMRI分析頗爲陌生。我試圖通過查看他們的大腦圖像來確定一個人正在考慮哪個對象(9個對象中的一個)。我正在使用https://openfmri.org/dataset/ds000105/上的數據集。所以,我通過輸入大腦圖像的2D切片來獲得9個物體中的1個輸出,從而使用神經網絡。有關每個步驟的詳細信息以及下面代碼中的圖像。使用pyBrain測試fMRI數據集時,神經網絡預測總是相同的。爲什麼?

import os, mvpa2, pyBrain 
    import numpy as np 
    from os.path import join as opj 
    from mvpa2.datasets.sources import OpenFMRIDataset 
    from pybrain.datasets import SupervisedDataSet,classification 

path = opj(os.getcwd() , 'datasets','ds105') 

of = OpenFMRIDataset(path) 

#12th run of the 1st subject 
ds = of.get_model_bold_dataset(model_id=1, subj_id=1,run_ids=[12]) 

#Get the unique list of 8 objects (sicissors, ...) and 'None'. 
target_list = np.unique(ds.sa.targets).tolist() 

#Returns Nibabel Image instance 
img = of.get_bold_run_image(subj=1,task=1,run=12) 

# Getting the actual image from the proxy image 
img_data = img.get_data() 

#Get the middle voxelds of the brain samples 
mid_brain_slices = [x/2 for x in img_data.shape] 

# Each image in the img_data is a 3D image of 40 x 64 x 64 voxels, 
# and there are 121 such samples taken periodically every 2.5 seconds. 
# Thus, a single person's brain is scanned for about 300 seconds (121 x 2.5). 
# This is a 4D array of 3 dimensions of space and 1 dimension of time, 
# which forms a matrix of (40 x 64 x 64 x 121) 

# I only want to extract the slice of the 2D images brain in it's top view 
# i.e. a series of 2D images 40 x 64 
# So, i take the middle slice of the brain, hence compute the middle_brain_slices 

DS = classification.ClassificationDataSet(40*64, class_labels=target_list) 

# Loop over every brain image 
for i in range(0,121): 

    #Image of brain at i th time interval 
    brain_instance = img_data[:,:,:,i] 

    # We will slice the brain to create 2D plots and use those 'pixels' 
    # as the features 

    slice_0 = img_data[mid_brain_slices[0],:,:,i] #64 x 64 
    slice_1 = img_data[:,mid_brain_slices[1],:,i] #40 x 64 
    slice_2 = img_data[:,:,mid_brain_slices[2],i] #40 x 64 

    #Note : we may actually only need one of these slices (the one with top view) 

    X = slice_2 #Possibly top view 

    # Reshape X from 40 x 64 to 1D vector 2560 x 1 
    X = np.reshape(X,40*64) 

    #Get the target at this intance (y) 
    y = ds.sa.targets[i] 
    y = target_list.index(y) 

    DS.appendLinked(X,y) 


print DS.calculateStatistics() 
print DS.classHist 
print DS.nClasses 
print DS.getClass(1) 

# Generate y as a 9 x 1 matrix with eight 0's and only one 1 (in this training set) 
DS._convertToOneOfMany(bounds=[0, 1]) 

#Split into Train and Test sets 
test_data, train_data = DS.splitWithProportion(0.25) 
#Note : I think splitWithProportion will also internally shuffle the data 

#Build neural network 
from pybrain.tools.shortcuts import buildNetwork 
from pybrain.structure.modules import SoftmaxLayer 
nn = buildNetwork(train_data.indim, 64, train_data.outdim, outclass=SoftmaxLayer) 

from pybrain.supervised.trainers import BackpropTrainer 
trainer = BackpropTrainer(nn, dataset=train_data, momentum=0.1, learningrate=0.01 , verbose=True, weightdecay=0.01) 
trainer.trainUntilConvergence(maxEpochs = 20) 

nn.activate(X_test[i])應採取2560個輸入和產生一個輸出概率,是嗎?在預測的y向量(形狀9 x 1)

所以,我假設應該給9個值中的最高值分配答案。但是,當我使用y_test [i]驗證它時,情況並非如此。此外,我爲每個測試樣本獲得X_test的相似值。這是爲什麼?

#Just splitting the test and trainset 
X_train = train_data.getField('input') 
y_train = train_data.getField('target') 
X_test = test_data.getField('input') 
y_test = test_data.getField('target') 

#Testing the network 
    for i in range(0,len(X_test)): 
    print nn.activate(X_test[i]) 
    print y_test[i] 

當我包括上面的代碼,這裏有X_test的一些值:

. 
. 
. 

nn.activated = [ 0.44403205 0.06144328 0.04070154 0.09399672 0.08741378 0.05695479 0.08178353 0.0623408 0.07133351] 
y_test [0 1 0 0 0 0 0 0 0] 

nn.activated = [ 0.44403205 0.06144328 0.04070154 0.09399672 0.08741378 0.05695479 0.08178353 0.0623408 0.07133351] 
y_test [1 0 0 0 0 0 0 0 0] 

nn.activated = [ 0.44403205 0.06144328 0.04070154 0.09399672 0.08741378 0.05695479 0.08178353 0.0623408 0.07133351] 
y_test [0 0 0 0 0 0 1 0 0] 
. 
. 
. 

所以該試樣在每一種情況下的id索引0,而不管樣品值的44.4%的概率。但實際值保持不變。

print 'print predictions: ' , trainer.testOnClassData (dataset=test_data) 

x = [] 
for item in y_test: 
    x.extend(np.where(item == 1)[0]) 
print 'print actual: ' , x 

這裏,輸出比較:

print predictions: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] 
print actual: [7, 0, 4, 8, 2, 0, 2, 1, 0, 6, 1, 4] 

所有的預測都爲第一個項目。我不知道問題是什麼。總的錯誤似乎在下降,這是一個好兆頭,但:

Total error: 0.0598287764931 
Total error: 0.0512272330797 
Total error: 0.0503835076374 
Total error: 0.0486402801867 
Total error: 0.0498354140541 
Total error: 0.0495447833038 
Total error: 0.0494208449895 
Total error: 0.0491162599037 
Total error: 0.0486775862084 
Total error: 0.0486638648161 
Total error: 0.0491337891419 
Total error: 0.0486965691406 
Total error: 0.0490016912735 
Total error: 0.0489939195858 
Total error: 0.0483910986235 
Total error: 0.0487459940103 
Total error: 0.0485516142106 
Total error: 0.0477407360102 
Total error: 0.0490661144891 
Total error: 0.0483103097669 
Total error: 0.0487965594586 

回答

1

我不能肯定 - 因爲我以前沒有一起使用所有這些工具,或者在這樣的專門工作項目 - 但我會看看文檔,並確保您的nn正在按照您的預期創建。

具體來說,它提到這裏:

http://pybrain.org/docs/api/tools.html?highlight=buildnetwork#pybrain.tools.shortcuts.buildNetwork

, 「如果經常性標誌設置,一個RecurrentNetwork將被創建,否則FeedForwardNetwork。」,你可以在這裏閱讀:

http://pybrain.org/docs/api/structure/networks.html?highlight=feedforwardnetwork

「FeedForwardNetworks是不適用於順序數據的網絡,每個輸入都被視爲獨立於任何先前或之後的輸入。」。

您是否打算創建一個「FeedForward」網絡對象?

您正在通過在索引上循環並激活基於FeedForwardNetwork對象的實例的每個"input"字段進行測試,文檔建議將該對象視爲與其他輸入無關。這可能就是爲什麼當你期待更好的收斂時,你每次都會得到類似的結果。

您使用參數model_id=1, subj_id=1,run_ids=[12]初始化您的數據集ds對象,表明您只查看單個主題和模型,但是在該模型下從該主題開始12個「運行」,對不對?

最有可能沒有什麼語義語法或錯誤的代碼,但是從PyBrain庫的推測和假設模型,參數和算法一般混亂。所以,不要爲了尋找代碼「錯誤」而撕掉你的頭髮。這對於記錄不足的圖書館來說絕對是一個常見的難題。

再一次,我可能不在基地,但根據我對類似工具和庫的經驗,最常見的做法是將一個非常複雜的過程並將其簡化爲幾行代碼的好處,它帶有一個TON完全不透明和固定的假設。

我的猜測是,你基本上重新運行的「新」的或獨立的訓練數據的「新」的測試,沒有所有的實際信息,並且你以爲你已經在前面的代碼行設置參數。你完全正確地認爲最高值(讀數:最大概率)是「最可能的」(這正是每個值的「可能性」)答案,特別是如果你的概率數組代表unimodal distribution

由於沒有明顯的代碼語法錯誤 - 就像在一個範圍內迭代器相當於列表[0,0,0,0,0,0]意外循環;您可以驗證,因爲您在打印y_test時重複使用i索引整數,其中nn.activate(X_test[i])不會發生變化 - 因此很可能發生的情況是您基本上每次都重新啓動測試,這就是爲什麼您獲得相同的結果,而不僅僅是類似的,但對於該方法結果的每個打印輸出都是相同的。

這是一個複雜的,但寫得很好,很好的說明問題,但不幸的是,我不認爲會有一個簡單的或公然明顯的解決方案。再次,您將獲得PyBrain簡化神經網絡,數據訓練,啓發式算法,數據讀取,採樣,統計建模,分類等等的好處,所有這些都簡化爲單行或雙行命令。有假設正在制定,他們噸。這就是文檔需要需要照亮的地方,當我們使用類似這樣的工具時,我們必須非常小心,它不僅僅是一個正確的語法問題,而且是一個實際上正確的(讀取:期望的)算法,假設以及所有這些。

祝你好運!

(PS - 開源庫還,儘管缺少文件,給你檢查源代碼,看看受益[假設和全部]他們實際上做:https://github.com/pybrain/pybrain

+0

嘿TommyP,感謝您及時的回覆。我的意圖是像你提到的那樣創建FeedForwardNetwork。在該模型中,我使用40 x 64 = 2560個特徵。但我只訓練了約100個樣本,並用其餘的測試。我認爲我必須增加樣本數量,所以我做了大約1400個小時。我仍然面臨同樣的問題。每次我在pybrain中使用函數時,都會參考文檔代碼。那裏沒問題。由於沒有愚蠢的錯誤(我認爲),我只需要尋找一個好的解決方案。再次感謝您的輸入。 :) –

+0

是的,對不起,我看不到任何明顯的東西,但我一直處於類似的情況,並被圖書館的假設絆倒。追查是一件很難的事情。我之前已經獲得了成功,通過實際訪問源代碼並將我的代碼中的函數調用替換爲庫中的源代碼,這樣您可以添加調試打印語句並修改假定的參數等。祝你好運! – 2016-09-18 11:45:08