上一篇文章讲解了练习嵌入相关的代码,这篇文章将会讲解学生嵌入相关的代码,编写学生嵌入时遇到了很多难点
1、模型的理解(模型的label是什么)
2、中间层的数据如何进行改变
3、如何自己编写loss函数
一、首先是模型理解
我们先看看作者给我们的模型图:
第一眼看到整个模型的时候,总感觉很怪,因为它预测输入的维度和练习输入的维度不一样,就感觉没法进行预测,于是我按我的理解对这模型进行了修改,修改如图:
产生这个想法的原因是,作者给出的损失函数,他的损失函数并不是计算最后一个状态产生的结果,而是计算所有状态产生的结果,于是我认为每个状态它都进行了预测。
以上就是我对这个模型的理解,label就是r,并且r是一个一维的向量,表示学生答题答对的概率。
二、中间层的数据如何改变
这个模型主要有三层,分别是LSTM层、ReLU层和Sigmoid层。根据模型可知,从LSTM层到ReLU层并不是LSTM的输出就是ReLU的输入,LSTM的输出(即中间层h)要和输入x进行连接,作为ReLU的输入。对中间层进行操作,需要用到Lambda层,总体流程如下:
def funtion1(x)#如何进行转换的函数
return 1
def funtion2(input_shape)#shape转换的函数
return 1
Lambda(funtion1, funtion2)
三、编写自己的loss函数
这个网上到处都是,我就简要的概括一下,对于损失函数IoU,需要对compile函数进行说明,需要对加载函数进行说明。
def IoU(y_true, y_pred): # 自己定义的损失函数
y_1=y_true*tf.math.log(y_pred)
print(y_1)
#exit()
y_2=(1-y_true)*tf.math.log(1-y_pred)
print(y_2)
#exit()
y_3=y_1+y_2
print(y_3)
#exit()
sum = -tf.reduce_sum(y_3)
print(sum)
#exit()
return sum
model.compile(loss=IoU, optimizer="adam", metrics=['accuracy'])
model = keras.models.load_model(Config.ModelDir + Config.model_output,custom_objects={'IoU':IoU})
具体代码
一、数据预处理(最初的x与r进行连接,并且作对做错是我随机生成的,没数据)
def processing_data():
with open(Config.ModelDir + Config.poetry_file, 'r') as f:
zero_array = np.array([0.0 for i in range(Config.dh)])
x=[]
y=[]
for line in f:
temp_Data=np.array(line.split())
temp_Data=temp_Data.astype(np.float32)
input_x.append(temp_Data)
# 制作答题情况
flag = random.randint(0, 1)
if flag == 0:
temp_Data = np.concatenate((zero_array,temp_Data))
else:
temp_Data=np.concatenate((temp_Data,zero_array))
x.append(temp_Data)
y.append(flag*1.0)
Config.T_train+=1
f.close()
x=np.array(x)
y=np.array(y)
x = x[None, :, :]
y = y[None, :]
return x,y
二、模型编写
def train_lstm(x_train=None, y_train=None):
global input_x
input_x=np.array(input_x)
input_x=input_x[None,:,:]
tf.compat.v1.disable_eager_execution()
model = Sequential()
# 获取LSTM层的信息
model.add(LSTM(Config.dh, input_shape=(Config.T_train, Config.VEC_SIZE), return_sequences=True))
model.add(Dropout(0.5))
# 中间层和输入进行连接
model.add(Lambda(input_Funtion, output_shape=_output_shape))
#model.add(Flatten())
model.add(Dense(Config.dy, input_shape=(), activation='relu'))
model.add(Dense(1, input_shape=(), activation='sigmoid'))
# 训练模型
# es = EarlyStopping(monitor='val_acc', patience=5)
model.compile(loss=IoU, optimizer="adam", metrics=['accuracy'])
batch_size = 20
epochs = 20
print(x_train.shape,y_train.shape)
print(type(x_train),type(y_train))
print(type(x_train[0]), type(y_train[0]))
print(type(x_train[0][0]), type(y_train[0][0]))
print(type(x_train[0][0][0]))
model.fit(x_train, y_train,
batch_size=batch_size,
epochs=epochs)# callbacks=[es]
model.save(Config.ModelDir + Config.model_output)
三、损失函数和Lambda层两个函数的编写
## intersection over union
def IoU(y_true, y_pred): # 自己定义的损失函数
y_1=y_true*tf.math.log(y_pred)
print(y_1)
#exit()
y_2=(1-y_true)*tf.math.log(1-y_pred)
print(y_2)
#exit()
y_3=y_1+y_2
print(y_3)
#exit()
sum = -tf.reduce_sum(y_3)
print(sum)
#exit()
return sum
# with tf.compat.v1.Session() as sess:
#
# array_y_true = y_true.eval(session=sess)
# array_y_pred = y_pred.eval(session=sess)
# exit()
#
# for i in range(Config.T_train):
# sum+= array_y_true[i] * np.log(array_y_pred[i])+(1-array_y_true[i])*np.log(1-array_y_pred[i])
# return -sum
def input_Funtion(x):
global input_x
print(input_x.shape)
input_x = tf.convert_to_tensor(input_x)
LSTM_Layer_Output = tf.concat([x,input_x],2)
print(LSTM_Layer_Output)
# exit()
# a=np.concatenate(x,input_x,axis=2)
# print(a.shape)
# exit()
# for i in range(0, x.shape[1]):
# a = []
# for j in range(Config.dh):
# a.append(x[0][i][j]) # 把当前的隐藏层加进数组
# for j in range(Config.dh):
# a.append(input_x[0][i][j]) # 把隐藏层对应的输入加进去
# LSTM_Layer_Output.append(a)
# LSTM_Layer_Output = np.array(LSTM_Layer_Output)
# LSTM_Layer_Output = LSTM_Layer_Output[None, :, :]
# print(LSTM_Layer_Output.shape)
# print(LSTM_Layer_Output.shape)
# print(type(tf.convert_to_tensor(LSTM_Layer_Output, tf.float32, name='t')))
return LSTM_Layer_Output
def _output_shape(input_shape):
shape=list(input_shape)
shape[-1]*=2
return tuple(shape)