Dueling Network 구현 (2)
14847 단어 DQ응ChainerDeepLearningpython2.7numpy
환경
GPU GTX1070
우분투 14.04
chainer 1.14.0
등
소개
Deuling Network의 코드를 구현하는 두 번째. 전회는
chainer/functions/connection/bilinear.py
를 확인했다.ぃ tp // 코 m / 설마 46 / ms / 3에 c187 아 5 f30fb416 예
이번에는 그것을 근거로 forward()와 backward()를 변경해 나간다.
forward() 변경
우선 순전파의 계산을 변경한다. 개요는 다음과 같습니다.
Numpy의 브로드캐스트라는 구조를 사용하면 크기가 다른 행렬 사이에서도 일정한 법칙 아래에 더할 수 있다. 이것을 사용하고 있다.
우선 브로드캐스트로 e1과 e2를 더한다. 이제 e2의 각 열에 e1이 더해집니다. 한편, e2를 열 방향으로 평균화한 것을 E2로서 생성한다. 다시 방송을 사용하여 먼저 더한 것에서 E2를 당기면 y가 구해진다.
forward() 함수내는 이하와 같이 수정한다.
def forward(self, inputs):
e1 = array.as_mat(inputs[0])
e2 = array.as_mat(inputs[1])
W = inputs[2]
#modified algorithm
y = e1 + e2 - e2.sum(1).reshape(len(e2), 1) / len(e2[0])
return y,
e1의 backward 구하기
우선 V측으로의 δ인 ge1을 구한다. 아래 그림과 같이 될 것이다. (계산이 잘못되면 알려주세요)
gy를 sum()으로 열 방향으로 더하면 좋을 것이다.
ge1 = cupy.sum(gy, axis=1).reshape(len(gy), 1).astype(dtype=gy.dtype, copy=False)
e2의 backward 구하기
다음에 A측의 δ인 e2를 구한다. 아래 그림과 같이 될 것이다.
궁리가 필요한 것은 (gy1+gy2+gy3) 부분일까. 여기는
cupy.sum()
함수로 값을 더한 다음 cupy.tile()
로 확장합니다. 따라서 forward () 코드는 다음과 같이 다시 작성됩니다. def backward(self, inputs, grad_outputs):
e1 = array.as_mat(inputs[0])
e2 = array.as_mat(inputs[1])
W = inputs[2]
gy = grad_outputs[0]
'''
xp = cuda.get_array_module(*inputs)
if xp is numpy:
gW = numpy.einsum('ij,ik,il->jkl', e1, e2, gy)
ge1 = numpy.einsum('ik,jkl,il->ij', e2, W, gy)
ge2 = numpy.einsum('ij,jkl,il->ik', e1, W, gy)
else:
kern = cuda.reduce('T in0, T in1, T in2', 'T out',
'in0 * in1 * in2', 'a + b', 'out = a', 0,
'bilinear_product')
e1_b = e1[:, :, None, None] # ij
e2_b = e2[:, None, :, None] # ik
gy_b = gy[:, None, None, :] # il
W_b = W[None, :, :, :] # jkl
gW = kern(e1_b, e2_b, gy_b, axis=0) # 'ij,ik,il->jkl'
ge1 = kern(e2_b, W_b, gy_b, axis=(2, 3)) # 'ik,jkl,il->ij'
ge2 = kern(e1_b, W_b, gy_b, axis=(1, 3)) # 'ij,jkl,il->ik'
'''
ge1 = cupy.sum(gy, axis=1).reshape(len(gy), 1).astype(dtype=gy.dtype, copy=False)
gy_sum = cupy.sum(gy, axis=1).reshape(len(gy), 1).astype(dtype=gy.dtype, copy=False)
gy_tile = cupy.tile(gy_sum, len(gy[0])).astype(dtype=gy.dtype, copy=False)
ge2 = (gy - gy_tile / len(gy[0])).astype(dtype=gy.dtype, copy=False)
gW = cupy.zeros(len(e1[0])*len(e2[0])*len(e2[0])).reshape(len(e1[0]), len(e2[0]), len(e2[0])).astype(dtype=gy.dtype, copy=False)
ret = ge1.reshape(inputs[0].shape), ge2.reshape(inputs[1].shape), gW
if len(inputs) == 6:
V1, V2, b = inputs[3:]
gV1 = e1.T.dot(gy)
gV2 = e2.T.dot(gy)
gb = gy.sum(0)
ge1 += gy.dot(V1.T)
ge2 += gy.dot(V2.T)
ret += gV1, gV2, gb
return ret
LIS로 성능 검증
LIS ver2의 example 게임에서 성능을 검증했다. LIS ver2에 관해서는 이쪽을 참조되었고.
ぃ tp // 이 m / 설마 46 / ms / 977 5010c1f000dc1d
40만 스텝 정도 학습시킨 결과가 아래의 그래프.
DQN(Mnih,2015)보다 성능이 오르고 있다고 생각하지 마라 ~. 제대로 된 비교는 하지 않았지만.
Atari 2600으로 성능 검증
Atari 2600의 BreakOut에서 성능을 검증했습니다. 결과는 아래의 그래프.
가로축이 episode이고 세로축이 각 episode에서 받은 reward. 확실히 상승하고 있군요.
코드 위치
LIS ver2용의 코드는 이쪽에 들었습니다.
htps : // 기주 b. 코 m / 마사타카 46 / 즈에 ぃ g
Atari2600용의 코드는 이쪽에 들었습니다.
htps : // 기주 b. 코 m / 마사타카 46 / 즈에 ぃ g 네토 rk
Reference
이 문제에 관하여(Dueling Network 구현 (2)), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/masataka46/items/5764c2a861721ac00140텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)