一、基本概念复习
1、自编码器
输入等于输出的神经网络模型
全连接层神经网络组成的最简单的自编码器只有三层结构,中间的隐藏层才是需要关注的地方。
在训练过程中,输入经过编码再解码,还原成原来的样子。
假如通过一组数据训练出了自编码器,拆掉解码器后,就可以使用编码器来表征数据了。
隐藏层的神经元数目远低于输入层,相当于我们用更少的特征去表征我们的输出数据,从而达到降维压缩的功能。
自编码器还有降噪的功能,把加噪声后的数据集当做输入,原本的数据集当做输出,训练一个自编码器,让它在训练中学习数据的规律,从而把噪声去掉。
多层自编码器:多个全连接神经网络隐藏层组成自编码器
卷积自编码器:能够很好保留二维信号的空间信息。
稀疏自编码器:普通自编码器的隐藏层加一个L1正则项,也就是一个训练惩罚项,这样训练出的编码器表征的特征更加的稀疏,从而能得到少且有用的特征项。
2、RNN
这篇文章讲得很好:https://blog.csdn.net/u013602059/article/details/104798224/
RNN比全连接神经网络多了h0,因此RNN神经元公式会多一项。训练过程同样是基于梯度下降。
整个RNN结构共享一组(U,W,b)
上一个隐藏层神经元的信息可以传递到下一个隐藏层神经元,从而形成一定的记忆能力。
多输入单输出
单输入多输出结构:如输入一个图像,输出描述文本。
多输入多输出结构:仅限于输入和输出等长,如作诗机器人。
输入输出不等长的多输入多输出RNN结构(Seq2Seq模型),如翻译机器人。
但是Seq2Seq有结构瑕疵:解码器的输入都是编码器的同一个输出,不管输入的语句是什么,编码器都会转换成同一个中间语义h。
由于一句话是有重点的,注意力机制应运而生。
注意力机制下的Seq2Seq模型输入变了,不是直接的序列输入,而是经过编码器转换的中间语义c,
这些输入c也各不相同,每一个c都是由权重w和解码器的隐藏层输出h加权组成。
比如c1的重点在“中”这个字,就可以通过更大的权值表示。
3、LSTM
由于RNN结构共享一组(U,W,b),在反向传播的过程中,由于不断连乘,(U,W,b)不是越来越大就是越来越小,这样就出现了梯度爆炸或梯度消失的情况。
LSTM外部结构没有任何变化,只是神经元变了,加入了输入门i,输出门o,遗忘门f,内部记忆单元α。
对于一个训练好的LSTM模型,每一个门都有各自的(U,W,b)。
当输入的序列不存在有用信息时,遗忘门的只就会接近1,输入门的值接近0,过去有用的信息就会被保存。
当输入的序列存在重要信息时,遗忘门的值就会接近0,输入门的值接近1,这样lstm对过去的记忆淡忘,记录新的重要记忆。
4、GRU
将lstm的遗忘门和输入门合并成更新门,将记忆单元与隐藏层合并成重置门,让整个结构运算更加简单。
当重置门接近0时,隐藏状态*忽略先前的隐藏状态,仅当前输入进行复位。
更新门控制从前一个隐藏状态将多少信息转移到当前隐藏状态,有助于RNN记住长期信息。
二、案例学习
1、预测股价趋势
原视频:https://www.bilibili.com/video/BV137411d75x
数据:quandl提供的免费数据集,首先安装它的库:pip install quandl
quandl提供的Google Stock数据集,包含多个变量:
损益的计算通常由股票当日收盘价决定,因此将收盘价作为预测目标。
这是一个多输入单输出的网络结构。
取50个交易日的数据作为输入,预测下一个交易日的收盘价,不断缩小真实收盘价和预测收盘价之间的loss即可。
流程:
(1)加载stock数据
(2)构造训练数据
(3)lstm建模
(4)预测stock
(5)查看拟合效果
import pandas as pd from datetime import date import quandl import matplotlib.pyplot as plt from sklearn.preprocessing import MinMaxScaler import numpy as np from keras.models import Sequential from keras.layers import Dense from keras.layers.recurrent import LSTM
start = date(2000,10,12) end = date.today() # 从2000年10月12一直到今天(实际只从2004-2018) google_stock = pd.DataFrame(quandl.get("WIKI/GOOGL",start_date=start,end_date=end)) print(google_stock.shape) google_stock.tail()
(3424, 12)
# 绘制历史收盘价trend图 plt.figure(figsize=(16,8)) plt.plot(google_stock['Close']) plt.show()
# 构造训练集与验证集 time_stamp = 50 # 时间点长度 google_stock = google_stock[['Open','High','Low','Close','Volume']] train = google_stock[0 : 2800+time_stamp] valid = google_stock[2800-time_stamp : ] # 归一化 scaler = MinMaxScaler(feature_range=(0,1)) scaled_data = scaler.fit_transform(train) # 训练集数据划分 x_train, y_train = [],[] for i in range(time_stamp, len(train)): x_train.append(scaled_data[i-time_stamp:i]) # 特征值是第i天的前50天的所有列(不包括第i天) y_train.append(scaled_data[i, 3]) # 目标值是从第i天的close(第3列),就一个值 x_train, y_train = np.array(x_train),np.array(y_train) print(x_train.shape) # 2800*50*5 print(y_train.shape) # 2800 # 验证集数据也做归一化并划分 scaled_data = scaler.fit_transform(valid) x_valid, y_valid = [],[] for i in range(time_stamp, len(valid)): x_valid.append(scaled_data[i-time_stamp:i]) y_valid.append(scaled_data[i,3]) x_valid, y_valid = np.array(x_valid),np.array(y_valid) print(x_valid[0]) # 1*50*5 y_valid[0]
(2800, 50, 5) (2800,)
0.07741396998730621
epochs = 3 batch_size = 16 # return_sequences:True代表输出一个序列,False代表输出一个值,默认为False # input_dim:输入单个样本特征值的维度(5),input_length:输入的时间点长度(50) model = Sequential() model.add(LSTM(units=100, return_sequences=True,input_dim=x_train.shape[-1],input_length=x_train.shape[1])) model.add(LSTM(units=50)) model.add(Dense(1)) model.compile(loss='mean_squared_error',optimizer='adam') model.fit(x_train, y_train, epochs=epochs, batch_size=batch_size, verbose=1)
Epoch 1/3 2800/2800 [==============================] - 10s 4ms/step - loss: 0.0055 Epoch 2/3 2800/2800 [==============================] - 8s 3ms/step - loss: 7.7182e-04 Epoch 3/3 2800/2800 [==============================] - 10s 3ms/step - loss: 6.1502e-04
closing_price = model.predict(x_valid) scaler.fit_transform(pd.DataFrame(valid['Close'].values)) # 反归一化 closing_price = scaler.inverse_transform(closing_price) y_valid = scaler.inverse_transform([y_valid]) rms = np.sqrt(np.mean(np.power((y_valid-closing_price),2))) print(y_valid-closing_price) print(rms) print(closing_price.shape) print(y_valid.shape)
184.50347568391422 (624, 1) (1, 624)
plt.figure(figsize=(16,8)) dict_data = { 'Predictions':closing_price.reshape(1,-1)[0], 'Close':y_valid[0] } data_pd = pd.DataFrame(dict_data) plt.plot(data_pd[['Close','Predictions']]) plt.show()
小结:self-attention的出现几乎取代了RNN和LSTM,需要关注更新更强的网络。
2、