2017-10-27 1 views
4

내 Keras 사용자 정의 손실 함수를 보라 :Keras/Tensorflow에서 슬라이스 기반 할당?

def custom_loss(y_true, y_pred): 
    sqerr = (y_true - y_pred)**2 
    sqerr[:,4:-1:7] = sqerr[:,4:-1:7] * ((y_true[:,2:-1:7]-y_true[:,3:-1:7])/y_true[:,2:-1:7])**2 
    return sqerr.mean() 

그러나 'sqerr이'오류

TypeError: 'Tensor' object does not support item assignment

이 코드의 결과는 그래서 jdehesa's answer과를 포함한 포스트 "How to do slice assignment in Tensorflow"을 읽고 있도록 NumPy와 배열이 아닌 GitHub page on this discussion. 그래서 여기 ... 내가 지금 가지고 무엇

def custom_loss(y_true, y_pred): 
    sqerr = K.square(y_true-y_pred) 

    sqerr = tf.Variable( sqerr , validate_shape=False) 
    with tf.control_dependencies([sqerr[:,4:-1:7].assign(sqerr[:,4:-1:7] * ((y_true[:,2:-1:7]-y_true[:,3:-1:7])/y_true[:,2:-1:7])**2)]): 
     sqerr = tf.identity(sqerr) 

    return K.mean(sqerr) 

...하지만 실제로 그것을 사용하는 시간이 올 때 분명히 나는 ​​그것을 서투르게 수선 해요 : 무슨 일이 일어나고

Traceback (most recent call last): File "my_awesome_nn.py", line 119, in setup_model

model.compile(loss=custom_loss, optimizer=opt) 

File "/opt/anaconda/envs/py35/lib/python3.5/site-packages/keras/engine/training.py", line 850, in compile

sample_weight, mask) 

File "/opt/anaconda/envs/py35/lib/python3.5/site-packages/keras/engine/training.py", line 465, in weighted

score_array = K.mean(score_array, axis=list(range(weight_ndim, ndim))) 

TypeError: 'NoneType' object cannot be interpreted as an integer

에서,이다 TF 슬라이싱은 일반 텐서가 아닌 변수에만 적용 할 수 있으므로 변수로 전송합니다. 그러나 변수로 형변환하면 모양을 알고 싶어하지만 모양은 그 지점에서 '동적으로 정의됩니다'(즉, 첫 번째 요소는 '?'). 따라서 validate_shape = False로 설정하면 실제로 변수를 정의 할 수 있지만 나중에 Keras가 원하는 차원 정보가 삭제됩니다. 관찰 : 나중에 따라서 출력

def custom_loss(y_true, y_pred): 
     sqerr = K.square(y_true-y_pred) 
     print("K.ndim(sqerr) #1 = ",K.ndim(sqerr)) 
     sqerr = tf.Variable( sqerr , validate_shape=False) 
     print("K.ndim(sqerr) #2 = ",K.ndim(sqerr)) 
     with tf.control_dependencies([sqerr[:,4:-1:7].assign(sqerr[:,4:-1:7] * ((y_true[:,2:-1:7]-y_true[:,3:-1:7])/y_true[:,2:-1:7])**2)]): 
      sqerr = tf.identity(sqerr) 

     return K.mean(sqerr) 

... 결과

K.ndim (sqerr) # 1 = 2

K.ndim (sqerr) # 2 = 없음

Keras training.py 코드에서 'ndim = K.ndim (score_array)'이라고 말하면 None으로 끝나고 NoneType 오류가 발생합니다.

내가 필요한 것을 수행하는 방법에 대해 알려줄 수 있습니까? 변수로 변환하지 않고 슬라이스 할 수없는 것처럼 보이고 동적 모양을 유지하는 동적 모양의 텐서에 대한 변수를 정의 할 수 없습니다.

내가 슬라이스 할당이 사용자 정의 손실을 방지 할 수 있다고 생각

+1

관련성 코드를 포함? 어디에서'score_array'를 계산합니까? 모델 선언 및 편집에 대한 더 많은 코드를 보여줄 수 있습니까? – DarkCygnus

+0

score_array가 Keras 배포판 내부에서 평가되는 것으로 표시되었으므로 코드를 포함 할 수는 있지만 내 코드는 아닙니다. https://github.com/fchollet/keras/blob/master/keras/engine/training.py. 그리고 그 모델은 손실이 조립되는 시점에 아직 구축되지 않았습니다. 현재이 문제는 변수 (캐스팅 슬라이스에 필요함)로 캐스팅 된 것으로 보이며 validate_shape = False가 필요합니다. 그 이유는 그 시점에서 텐서 모양이 '느슨하게 정의되어 있기 때문입니다. 그러나 K.dim (sqerr) = None이됩니다. 나는 이것을 반영하기 위해 게시물을 편집 할 것입니다 ... – sh37211

답변

2

(이것은 내가 바로 위의 "중간 3 라인"을 생략하고 내 사용자 정의 손실이 MSE 정규 할 경우 완전히 작동하는 코드입니다). sqerr[:, 4:-1:7]의 손실 값을 조정하려면 총 손실에서 원래 값을 뺀 다음 조정 된 손실 값을 다시 추가 할 수 있습니다.

def custom_loss_keras(y_true, y_pred): 
    # first sum up the squared error column-wise 
    sqerr = K.square(y_true - y_pred) 
    loss = K.sum(sqerr, axis=-1) 

    # subtract the loss for the sliced part 
    loss -= K.sum(sqerr[:, 4:-1:7], axis=-1) 

    # add back the adjusted loss for the sliced part 
    denominator = K.maximum(y_true[:, 2:-1:7], K.epsilon()) # handle zero-division 
    numerator = y_true[:, 2:-1:7] - y_true[:, 3:-1:7] 
    loss += K.sum(sqerr[:, 4:-1:7] * K.square(numerator/denominator), axis=-1) 

    # take average 
    ncols = K.int_shape(y_pred)[-1] 
    loss /= ncols 
    return K.mean(loss) 
당신은 원래 NumPy와 버전과 비교하여이 기능을 확인할 수 있습니다

: 당신이 시도 할 수

def custom_loss_numpy(y_true, y_pred): 
    sqerr = (y_true - y_pred)**2 
    sqerr[:,4:-1:7] = sqerr[:,4:-1:7] * ((y_true[:,2:-1:7]-y_true[:,3:-1:7])/y_true[:,2:-1:7])**2 
    return sqerr.mean() 

y_true = np.random.rand(50, 1000) 
y_pred = np.random.rand(50, 1000) 

print(custom_loss_numpy(y_true, y_pred)) 
889.992075384 

print(K.eval(custom_loss_keras(K.variable(y_true), K.variable(y_pred)))) 
889.992 
+0

우수하고 모범답! 고맙습니다! – sh37211

관련 문제