Почему многопроцессорная обработка дает другие результаты, чем обычные функции - PullRequest
0 голосов
/ 09 апреля 2019

Я хочу, чтобы процесс обучения моего NN был короче, так что я использую многопроцессорность. Однако полученные результаты неверны - сеть не обучается правильно (она обучается при использовании тех же функций, но без многопроцессорной обработки). У меня две проблемы. Первый - если я введу некоторую переменную и использую ее внутри функции, реализованной с помощью многопроцессорной обработки, она будет работать нормально. Проблема в том, что когда я запускаю код и после этого я изменяю переменную вручную (например, >>> a + = 10), функция внутри многопроцессорной обработки не видит никаких изменений. Он работает так, как будто переменная такая же, как в начале. Вторая проблема - после принудительного ввода «свежих» данных в каждый раз при запуске функции результаты по-прежнему неверны. У меня есть (другая) проблема, что некоторые из начальных весов и смещений слишком велики или малы, и небольшое изменение их значений не влияет на общий результат. Таким образом, некоторые из выходных градиентов должны быть равны 0, это верно в случае запуска обучения без многопроцессорной обработки. Когда я использую многопроцессорность для обучения, каждый градиент отличается от 0, и они не являются копиями одного результата. У меня заканчиваются идеи, в чем может быть проблема, и мне нужна ваша помощь, пожалуйста.

Это мой код, в котором я запускаю multiTrain ():

def calcGradM(data):

    print(data[0])
    VC=-epsilon/score0
    for i in data:

        if i[2]==1:
            deltaMaskWB1[i[3]][0][i[4]]=i[0]*VC
            deltaMaskWB1[i[3]][1][i[4]]=i[1]*VC
        if i[2]==2:
            deltaMaskWB2[i[3]][0][i[4]]=i[0]*VC
            deltaMaskWB2[i[3]][1][i[4]]=i[1]*VC

def Grad(score0,lvl,layer,i):

    maskW1=np.zeros_like(wb1)
    maskW2=np.zeros_like(wb2)
    maskB1=np.zeros_like(wb1)
    maskB2=np.zeros_like(wb2)

    if layer==1:
        maskW1[lvl][0][i]=epsilon
        maskB1[lvl][1][i]=epsilon
    if layer==2:
        maskW2[lvl][0][i]=epsilon
        maskB2[lvl][1][i]=epsilon

    return([result(wb1+maskW1,wb2+maskW2)- 
score0,result(wb1+maskB1,wb2+maskB2)-score0,layer,lvl,i])

def result(L1,L2):
    ans=[]
    for i in range(pos1,pos2):
        ans.append(netResponse(L1,L2,i))
    return np.sum(ans)

def multiTrain():
    T0=time.time()
    global score0
    score0=result(wb1,wb2)
    if __name__ == '__main__':
        pool = multiprocessing.Pool(4)
        for l in range(2):
            calcGradM(pool.map(partial(Grad,score0,l,2), range(hidLen)))
        for l in range(hidLen):
            calcGradM(pool.map(partial(Grad,score0,l,1), range(len(neuronsIn))))
        pool.close()
    print(time.time()-T0)

1 Ответ

0 голосов
/ 09 апреля 2019

Переменные неявно разделяются при чтении и записи между многопроцессными родителями и детьми.

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

Дети могут (в зависимости от режима порождения) наследовать состояние глобалов в момент их отделения от родительского процесса, но вы не должны на это полагаться.

В руководстве multiprocessing есть раздел о состоянии общего доступа между процессами .

Эта статья может также помочь вам.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...