几周前要用自动编码器模拟一个通信系统,开始学习tensorflow,后来发现Keras对新手更加友好,便入坑Keras,但由于keras集成度很高,很多细节不是很好实现,导致模拟模拟通信系统的过程出现了些小问题,在此记录下来。
常规的自动编码器网络:
我需要实现的网络:
出现的问题:
信道可以用矩阵来代替,也就是我需要对编码器的输出乘上一个矩阵,然后将其送入解码器,因为keras搭建网络时操作对象是Layer,不能是变量或tensor,所以这个地方直接将编码器的输出和矩阵相乘赋值给变量,再将变量输入到解码器会报错,利用tensorflow中的tf.matmul()语句将结果赋值给张量后传入给解码器仍然会报错。自动编码器网络结构部分代码如下:
#编码器
input_img = Input(shape=(4,))
encoded = Dense(32, activation='relu')(input_img)
encoded = Dense(32, activation='relu')(encoded)
encoded = Dense(7, activation='relu')(encoded)
#信道
encoded_output1 = tf.matmul(encoded,h)
encoded_output2 = keras.layers.noise.GaussianNoise(sigma_2)(encoded_output1)
#解码器
decoded = Dense(32, activation='relu')(encoded_output2)
decoded = Dense(32, activation='relu')(decoded)
decoded = Dense(4, activation='sigmoid')(decoded)
程序运行后报错如下:
解决方法:
利用keras中的Lambda层自定义一个层。
Lambda层的作用是自定义层,如果只是对数据进行操作,而网络中的参数没有更新,那么便可以利用Lambda进行自定义层。步骤如下:
1.首先定义一个函数,我需要的是编码器的输出乘上一个矩阵,所以定义一个相乘的函数如下:
def mul(x):
return tf.matmul(x,h)
#x表示编码器的输出,h表示矩阵
2.利用Lambda定义一个层
encoded_output1 = Lambda(mul)(encoded)
#mul表示第一步定义的函数,encoded表示编码器的输出
完整代码如下:
def mul(x):
return tf.matmul(x,h)
#编码器
input_img = Input(shape=(4,))
encoded = Dense(32, activation='relu')(input_img)
encoded = Dense(32, activation='relu')(encoded)
encoded = Dense(7, activation='relu')(encoded)
#信道
encoded_output1 = Lambda(mul)(encoded)
encoded_output2 = keras.layers.noise.GaussianNoise(sigma_2)(encoded_output1)
#解码器
decoded = Dense(32, activation='relu')(encoded_output2)
decoded = Dense(32, activation='relu')(decoded)
decoded = Dense(4, activation='sigmoid')(decoded)
再次运行程序,就不会在出现AttributeError: ‘NoneType’ object has no attribute ‘_inbound_nodes’。
123456