대게 기본적인 신호처리 쪽 딥러닝들은 noisy signal $y$ 을 input으로 넣고 clean signal $x$을 output이 되도록 학습하면서 MAE나 MSE 이런걸 쓴다.
$\min \sum_{l,k} (x(l,k) – \widehat{x}(l,k))^2$
hat이붙은건 추정치.. l과 k는 각각 시간과 주파수를 나타내는데..
model = ...
loss_fn = tf.keras.losses.MeanSquaredError()
model = Model(inputs=input, outputs=output)
model.compile(loss=loss_fn, optimizer=opt)
model.summary()
뭐 대충 위 코드처럼 하면 된다. 또,
$\min\sum_{l,k} (m(l,k) – \widehat{m}(l,k))^2$
처럼 직접적으로 mask를 추정해서
$\widehat{x}(l,k)=\widehat{m}(l,k)y(l,k)$
하는 방법도 있다. 이 방법은 미리 mask를 계산해야 하는 귀찮음이 있고 이런 방법 대신에
$\min\sum_{l,k} (x(l,k) – \widehat{m}(l,k) y(l,k))^2$
하면서, $\widehat{m}(l,k)$를 원하는 사람이 있다.
물론, signal approximation 방식이 내 분야에서는 성능이 더 좋게 나온다. matlab이라면 그냥 직접 gradients 구해서 할텐데, 귀찮고 실행 속도가 너무 느려;;
python은 익숙하지 않아서 찾아보니 구현해놓은 게 없네… 스택오버플로우에서 알려주는 방법대로 했는데 gradient 전파가 안된다는 에러..
아래처럼 하면 되더라..
def SA_loss(y_true, y_pred, inputs):
d = K.mean(K.square(y_true-y_pred*inputs))
return d
def create_model(...):
input1 = Input(shape=(length))
input2 = Input(shape=(length))
out = Dense(units=2048)(input1)
out = PReLU()(out)
out = BatchNormalization()(out)
out = Dropout(0.2)(out)
o = Model(inputs=[input1, input2], outputs=out)
o.add_loss( SA_loss( input1, out, input2 ) )
o.compile(loss=None, optimizer=opt)
o.summary()
return o
class Dataloader(Sequence):
.... #잘 구현..
return [input1, input2], input2 #input2는 target
model = create_model()
model.fit(dataloader, ...)
실제 테스트 단계에서는
model = load_model(...)
model = Model(model.input[0], model.output)
result = model.predict(...)
잘 돌아간다.
매번 느끼지만, python 만질 때마다 코딩하는 느낌은 안든다.
‘으으.. 어떻게 코드 섞어야 하지..’ 그렇지만 좀 고민하는 고통을 겪으면 결과 나오는 속도가 빨라서 쓴다..