2016-09-17 20 views
0

Я новичок в анализе МРМР. Я пытаюсь определить, какой объект (из 9 объектов) человек думает только, глядя на свои изображения мозга. Я использую набор данных на https://openfmri.org/dataset/ds000105/. Итак, я использую нейронную сеть, вводя 2D-фрагменты изображений мозга, чтобы получить результат как 1 из 9 объектов. На каждом шаге и изображениях приведено подробное описание.Прогнозы нейронной сети всегда одинаковы при тестировании набора данных fMRI с помощью pyBrain. Зачем?

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] 
. 
. 
. 

Таким образом, вероятность того, что испытательный образец индекса 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"?

Вы тестируете, перебирая индекс и активизируя каждое поле "input", основанное на создании объекта FeedForwardNetwork, которое, по мнению документации, рассматривается как независимое от других входов. Возможно, поэтому вы получаете одинаковые результаты каждый раз, когда ожидаете улучшения конвергенции.

Вы инициализируете свой объект ds объект с параметрами model_id=1, subj_id=1,run_ids=[12], предполагая, что вы смотрите только на один объект и модель, но 12 «работает» от этого объекта под этой моделью, не так ли?

Скорее всего, нет ничего семантически или грамматически неправильно с вашим кодом, но общая путаница из предполагаемых и предполагаемых моделей, параметров и алгоритмов библиотеки PyBrain. Так что не разрывайте волосы, ища код «ошибки»; это, безусловно, обычная трудность с недостаточно документальными библиотеками.

Опять же, я могу быть вне базы, но, по моему опыту с подобными инструментами и библиотеками, чаще всего, что использование чрезвычайно сложного процесса и его упрощение до пары десятков строк кода поставляется с TON абсолютно непрозрачных и фиксированных допущений.

Я предполагаю, что вы, по сути, повторно запускаете «новые» тесты на «новые» или независимые данные обучения без всякой фактической информации и параметров, которые, по вашему мнению, были настроены в предыдущих строках кода. Вы точно верны, что наибольшее значение (считайте: наибольшая вероятность) является «наиболее вероятным» (это именно то, что каждое значение является «вероятностью»), особенно если ваш массив вероятностей представляет собой unimodal distribution.

Поскольку нет очевидных ошибок синтаксиса кода - например, случайное переключение на итератор диапазона, эквивалентный списку [0,0,0,0,0,0]; которую вы можете проверить, потому что вы повторно используете значение i индекса в печати y_test, которое меняется, и результат nn.activate(X_test[i]) не меняется - тогда, скорее всего, происходит то, что вы вначале перезапускаете свой тест каждый раз, и именно поэтому вы получая идентичный результат, не только похожий, но и идентичный для каждой распечатки результатов метода nn.activate(...).

Это сложный, но хорошо написанный и хорошо иллюстрированный вопрос, но, к сожалению, я не думаю, что будет простое или откровенно очевидное решение.

Опять же, вы получаете преимущества упрощенного подхода PyBrain к нейронным сетям, обучения данных, эвристике, чтению данных, выборке, статистическому моделированию, классификации и т. Д. И т. Д., Все они сводятся к однострочным или двум линейным командам , Там являются допущениями, ТОННЫ из них. Вот для чего требуется документация , и мы должны быть очень осторожны, когда используем такие инструменты, что это не просто вопрос правильного синтаксиса, а фактически правильный (читаемый: ожидаемый) алгоритм, предположения и все такое.

Удачи вам!

(PS - Открытые библиотеки источников также, несмотря на отсутствие документов, дать вам преимущество проверки исходного кода, чтобы увидеть [предположения и все], что они на самом деле делают: https://github.com/pybrain/pybrain)

+0

Эй TommyP, Спасибо за быстрый ответ. Мое намерение состояло в том, чтобы создать FeedForwardNetwork, как вы упомянули. В модели я использую 40 x 64 = 2560 функций. Но я тренировал его только около 100 образцов и использовал остальные для тестирования. Я думал, что мне нужно увеличить количество образцов, поэтому я сделал около 1400-иш. Я все еще получаю ту же проблему. Каждый раз, когда я использую функцию в pybrain, я ссылаюсь на код документов. Нет проблем. Поскольку нет глупых ошибок (я думаю), мне просто нужно искать хорошее решение. Еще раз спасибо за ваш вклад. :) –

+0

Да, извините, я не мог видеть ничего очевидного, но я был в подобных ситуациях и искажен по предположениям библиотеки. Трудно отследить. Раньше я имел успех, фактически перейдя к исходному коду и заменяя вызов функции в своем коде исходным кодом из библиотеки, таким образом вы можете добавлять отладочные заявления печати и изменять предполагаемые параметры и т. Д. Удачи! –