Keras: 在LSTM网络中添加MDN层

我的简短问题:给定舞蹈序列的训练数据,以下详细描述的长短期记忆网络是否适用于生成新的舞蹈序列?

背景:我正在与一位希望使用神经网络生成新舞蹈序列的舞者合作。她向我发送了2016年的chor-rnn论文,该论文使用在末端带有混合密度网络层的LSTM网络完成了这一任务。然而,在我向我的LSTM网络添加MDN层后,我的损失值变为负数,结果看起来很混乱。这可能是因为训练数据非常少,但在扩展训练数据规模之前,我想验证模型的基本原理。如果有人能指出下面的模型是否忽略了某些基本要素(这很有可能),我将非常感谢他们的反馈意见。

我输入网络的样本数据(下面的X)的形状为(626, 55, 3),对应于626个时间快照中的55个身体位置,每个位置有3个坐标(x, y, 然后是z)。所以X1[11][2]是时间1时第11个身体部位的z位置:

import requestsimport numpy as np# 下载数据requests.get('https://s3.amazonaws.com/duhaime/blog/dancing-with-robots/dance.npy')# X.shape = 时间间隔, 身体部位数, 3X = np.load('dance.npy')

为了确保数据被正确提取,我可视化了X的前几个帧:

import mpl_toolkits.mplot3d.axes3d as p3import matplotlib.pyplot as pltfrom IPython.display import HTMLfrom matplotlib import animationimport matplotlibmatplotlib.rcParams['animation.embed_limit'] = 2**128def update_points(time, points, X):  arr = np.array([[ X[time][i][0], X[time][i][1] ] for i in range(int(X.shape[1]))])  points.set_offsets(arr) # 设置x, y值  points.set_3d_properties(X[time][:,2][:], zdir='z') # 设置z值def get_plot(X, lim=2, frames=200, duration=45):  fig = plt.figure()  ax = p3.Axes3D(fig)  ax.set_xlim(-lim, lim)  ax.set_ylim(-lim, lim)  ax.set_zlim(-lim, lim)  points = ax.scatter(X[0][:,0][:], X[0][:,1][:], X[0][:,2][:], depthshade=False) # x,y,z值  return animation.FuncAnimation(fig,    update_points,    frames,    interval=duration,    fargs=(points, X),    blit=False    ).to_jshtml()HTML(get_plot(X, frames=int(X.shape[0])))

这会生成一个这样的小舞蹈序列:

enter image description here

到目前为止一切顺利。接下来,我对x, y和z维度的特征进行居中处理:

X -= np.amin(X, axis=(0, 1))X /= np.amax(X, axis=(0, 1))

使用HTML(get_plot(X, frames=int(X.shape[0])))可视化处理后的X,显示这些线条很好地居中了数据。接下来,我使用Keras的Sequential API构建模型本身:

from keras.models import Sequential, Modelfrom keras.layers import Dense, LSTM, Dropout, Activationfrom keras.layers.advanced_activations import LeakyReLUfrom keras.losses import mean_squared_errorfrom keras.optimizers import Adamimport keras, os# 配置look_back = 32 # 用于预测时间i位置的前几个时间框架数lst_cells = 256 # 每个LSTM“层”中的单元数n_features = int(X.shape[1]) * int(X.shape[2]) # 每个`m`模型要预测的坐标值数input_shape = (look_back, n_features) # 输入形状m = 32 # 要构建的高斯模型数量# 设置布尔值,控制是否使用MDNuse_mdn = Truemodel = Sequential()model.add(LSTM(lstm_cells, return_sequences=True, input_shape=input_shape))model.add(LSTM(lstm_cells, return_sequences=True))model.add(LSTM(lstm_cells))if use_mdn:  model.add(MDN(n_features, m))  model.compile(loss=get_mixture_loss_func(n_features, m), optimizer=Adam(lr=0.000001))else:  model.add(Dense(n_features, activation='tanh'))  model.compile(loss=mean_squared_error, optimizer='sgd')model.summary()

模型构建完成后,我对X中的数据进行整理以准备训练。我们希望通过检查前look_back时间片中每个身体部位的位置来预测某个时间的55个身体部位的x, y, z位置:

# 将训练数据调整为正确的形状train_x = []train_y = []n_time, n_obs, n_attrs = [int(i) for i in X.shape]for i in range(look_back, n_time-1, 1):  train_x.append( X[i-look_back:i].reshape(look_back, n_obs * n_attrs) )  train_y.append( X[i+1].ravel() )train_x = np.array(train_x)train_y = np.array(train_y)

最后,我训练模型:

from livelossplot import PlotLossesKeras# 拟合模型model.fit(train_x, train_y, epochs=1024, batch_size=1, callbacks=[PlotLossesKeras()])

训练后,我可视化模型生成的新时间片段:

# 生成`n_frames`个新输出时间片段n_frames = 3000# 用前`look_back`个动画帧初始化要绘制的数据data = X[0:look_back]x0, x1, x2 = [int(i) for i in train_x.shape]d0, d1, d2 = [int(i) for i in data.shape]for i in range(look_back, n_frames, 1):  # 获取模型对时间`i`的下一个位置的预测  result = model.predict(train_x[i].reshape(1, x1, x2))  # 如果使用混合密度网络,则提取描述顶点位置的值  if use_mdn:    result = np.apply_along_axis(sample_from_output, 1, result, n_features, m, temp=1.0)  # 将结果重塑为`X`中的行形式  result = result.reshape(1, d1, d2)  # 将结果推入`train_x`观测的形状  stacked = np.vstack((data[i-look_back+1:i], result)).reshape(1, x1, x2)  # 将结果添加到`train_x`观测中  train_x = np.vstack((train_x, stacked))  # 将结果添加到用于绘制的数据集中  data = np.vstack((data[:i], result))

如果我将上面的use_mdn设置为False,而改用简单的平方误差和损失(L2损失),那么生成的可视化看起来有点怪异,但仍然大致保持人形。

然而,如果我将use_mdn设置为True,并使用自定义的MDN损失函数,结果就非常奇怪。我认识到MDN层增加了大量需要训练的参数,并且可能需要成倍增加训练数据量才能达到与L2损失函数输出一样的人形输出。

尽管如此,我想问一下是否有其他人比我更广泛地使用过神经网络模型,看看上述方法是否有什么根本性的问题。对于这个问题的任何见解都将非常有帮助。


回答:

天啊,我成功了 [gist]!这是MDN类:

Related Posts

Flatten and back keras

我正在尝试使用自编码器获取简单向量中的值 这是我的代码…

如何按索引访问PyTorch模型参数

如果我的网络有10层,包括偏置项,如何仅通过索引访问第…

Python中多元逻辑回归显示错误

我试图使用逻辑回归进行预测,并使用Python和skl…

在MACOS上安装NLTK

我在我的2015款Mac Pro上尝试安装NLTK,操…

如何在R中将通过RFE选择的变量插入到机器学习模型中?

我想使用递归特征消除方法来选择最重要的特征,然后将这些…

CountVectorizer 错误:ValueError: setting an array element with a sequence

我有一个包含144条学生反馈的数据集,其中有72条正面…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注