뉴럴넷의 가중치를 실수치 유전적 알고리즘으로 최적화해 본다 ~그 3:TensorFlow 대응【실패】~

지난번 만든 OpenAI Gym을 NeuroEvolution(뉴럴넷+실수치 유전적 알고리즘)으로 학습하는 구현을 TensorFlow를 사용해 고속화할 수 없을까라고 생각해 보았습니다.

결과적으로 실패했습니다. . . 2~4배의 시간이 걸리게 되었습니다.
다른 사람이 쓸데없는 구현을하지 않도록 미주를하지 않도록 메모로 남겨 둡니다.

TensorFlow에 대해 다시 복습



TensorFlow화할 때, 걸린 점을 정리합니다.

텐서 객체는 숫자형 배열이 아닙니다.



numpy와 같은 계산을 할 수 있는 엉망이 됩니다만, 어디까지나 조작(오퍼레이션)을 담은 상자입니다.

tensor.py
import tensorflow as tf
import numpy as np

def sum(a , b) :
    return a + b

#TensorFlowの計算
tfa = tf.constant([1,2])
tfb = tf.constant([10,20])
tfc = tf.constant([100,200])

print('tfa : {0} : <type={1}>'.format(tfa  , type(tfa))) 
#>tfa : Tensor("Const:0", shape=(2,), dtype=int32) : <type=<class 'tensorflow.python.framework.ops.Tensor'>>

sum_op = sum(tfa , tfb)
print('sum_op : {0} : <type={1}>'.format(sum_op  , type(sum_op))) 
#>sum_op : Tensor("add:0", shape=(2,), dtype=int32) : <type=<class 'tensorflow.python.framework.ops.Tensor'>>

sum_op = sum(sum_op , tfc)
print('sum_op : {0} : <type={1}>'.format(sum_op  , type(sum_op))) 
#>sum_op : Tensor("add_1:0", shape=(2,), dtype=int32) : <type=<class 'tensorflow.python.framework.ops.Tensor'>>

sess = tf.Session()
result = sess.run(sum_op)
print('result : {0} : <type={1}>'.format(result  , type(result))) 
#>result : [111 222] : <type=<class 'numpy.ndarray'>>

#numpyの計算
npa = np.array([1,2])
npb = np.array([10,20])
npc = np.array([100,200])
npsum = sum(npa , npb)
npsum = sum(npsum , npc)
print('npsum : {0} : <type={1}>'.format(npsum  , type(npsum))) 
#>npsum : [111 222] : <type=<class 'numpy.ndarray'>>
sess.run() 에서 작업을 실행하면 처음으로 계산 결과를받을 수 있습니다.

변수가 아니므로 텐서 객체를 numpy 함수에 전달하면 오류가 발생합니다.

TensorError.py
import tensorflow as tf
import numpy as np
#ReLU関数
def relu(x):
    return np.maximum(0, x)

npa = np.array([-1,2])
nprelu = relu( npa )
print('nprelu : {0} : <type={1}>'.format(nprelu  , type(nprelu))) 
#> nprelu : [0 2] : <type=<class 'numpy.ndarray'>>

tfa = tf.constant([-1,2])
relu_op = relu(tfa )

#> TypeError: Using a `tf.Tensor` as a Python `bool` is not allowed. Use `if t is not None:` instead of `if t:` to test if a tensor is defined, and use TensorFlow ops such as tf.cond to execute subgraphs conditioned on the value of a tensor.

작업 작성 후 TensorFlow 상수를 다시 작성해도 반영되지 않습니다.



TensorConstSum.py
import tensorflow as tf
import numpy as np

def sum(a , b) :
    return a + b

tfc = tf.constant([1,2])
b = 10
sum_op = sum(tfc , b)

sess = tf.Session()

result = sess.run(sum_op)
print('result : {0} : <type={1}>'.format(result  , type(result))) 
#>result : [11 12] : <type=<class 'numpy.ndarray'>>

tfc = tf.constant([10,20])
b = 100
result = sess.run(sum_op)
print('result : {0} : <type={1}>'.format(result  , type(result))) 
#>result : [11 12] : <type=<class 'numpy.ndarray'>>

TensorFlow 변수를 업데이트하려면 assign()를 사용해야 합니다.



TensorVariableSum.py
import tensorflow as tf
import numpy as np

def sum(a , b) :
    return a + b

tfc = tf.constant([1,2])
tfv = tf.Variable(10)

sum_op = sum(tfc , tfv)

sess = tf.Session()
sess.run(tf.global_variables_initializer()) 

result = sess.run(sum_op)
print('result : {0} : <type={1}>'.format(result  , type(result))) 
#>result : [11 12] : <type=<class 'numpy.ndarray'>>

#変数 更新
assign_op = tfv.assign(100)
sess.run(assign_op)
result = sess.run(sum_op)
print('result : {0} : <type={1}>'.format(result  , type(result))) 
#>result : [101 102] : <type=<class 'numpy.ndarray'>>

NN+ 실수치 GA의 TensorFlow 대응



OpenAI Gym을 NN+ 실수치 GA로 학습할 때, 1개 개체 시뮬레이션의 처리 흐름은 다음과 같이 하고 있었습니다.



OpenAI Gym은 numpy를 사용하여 구현되어 있기 때문에 TensorFlow화할 수 있는 것은 "NN에서 행동을 추론"부분에만. . 덧붙여 NN의 가중치와 바이어스를 TensorFlow의 변수로 표현하면, 개체마다 변수의 갱신 처리가 필요하게 됩니다.

결과



GoogleColaboratory의 GPU 모드와 CPU 모드에서 속도를 측정하고 있습니다. 50개 개체를 평가한 평균입니다(시간 취득이나 출력에 드는 비용도 있으므로, 어디까지나 기준으로)


측정 구간
TensorFlow 없음(GPU)
TensorFlow 대응(GPU)
TensorFlow 대응(CPU)


가중치와 바이어스 세트
23[μsec]
21963[μsec]
25191[μsec]

200step 시뮬레이션
88587[μsec]
255974[μsec]
186580[μsec]

합계
88610[μsec]
277937[μsec]
211771[μsec]


「가중과 바이어스 세트」에 시간이 걸리는 것은 상정내입니다만, 시뮬레이션에도 시간이 걸리고 있습니다.
1step의 시뮬레이션 내역입니다.


측정 구간
TensorFlow 없음(GPU)
TensorFlow 대응(GPU)
TensorFlow 대응(CPU)


NN에서 행동을 추론
132[μsec]
926[μsec]
559[μsec]

OpenAI Gym으로 1 단계 시뮬레이션
36[μsec]
53[μsec]
55[μsec]

합계
168[μsec]
979[μsec]
614[μsec]


고속화하고 싶었던 「NN로 행동을 추론」 자체에 시간이 걸려 버리고 있습니다. 그리고 GPU보다 CPU가 빠릅니다. . TensorFlow 튜토리얼 를 보는 한, 메모리의 카피가 넥이 되어 있을 것 같은 느낌입니다.
「OpenAI Gym으로 1step 시뮬레이트」로 시간이 걸리게 되어 있는 것은, 컨텍스트의 전환이라던가요? ?

결론



BP를 이용한 이미지 인식 과 같이, 1회의 오퍼레이션 실행으로 대량의 배치 처리를 실시하는 것 같은 학습이 아닌 한, TensorFlow로 구현하는 메리트는 없을 것 같네요.

좋은 웹페이지 즐겨찾기