lstm学习

原文链接:
https://blog.csdn.net/zzukun/article/details/49968129

代码(python3.7 + tensorflow2.0):

# -- coding: utf-8 --
import copy
import numpy as np
from time import time


# sigmoid函数
def sigmoid(x):
    return 1 / (1 + np.exp(-x))


# sigmoid函数的导数,这里out=sigmoid(x)
def sigmoid_out_to_derivative(output):
    return output * (1 - output)


# 获取二进制对应关系,将所有数转二进制(我们的数据生成器)
int2binary = {}  # 字典格式
binary_dim = 8  # 二进制的最长位数
largest_number = pow(2, binary_dim)  # 最大值
binary = np.unpackbits(np.array([range(largest_number)], dtype=np.uint8).T, axis=1)  # unpackbits函数, 将整数转为2进制
for i in range(largest_number):
    int2binary[i] = binary[i]  # 使用字典格式赋值,得到结果类似{0:array([0,0,0,0,0,0,0,1], dtype = uint8), 1:array(......}


def main():
    start = time()

    # 设置学习速率
    alpha = 0.1
    # 输入层
    input_dim = 2
    # 隐藏层神经元个数
    hidden_dim = 16
    # 输出层
    output_dim = 1

    # 连接输入层与隐藏层的权值矩阵2行16列,取值区间为[-1, 1),使用区间内随机数初始化
    synapse_0 = 2 * np.random.random((input_dim, hidden_dim)) - 1
    # 连接隐藏层与输出层的权值矩阵16行1列,取值区间为[-1, 1),使用区间内随机数初始化
    synapse_1 = 2 * np.random.random((hidden_dim, output_dim)) - 1
    # 连接(上一个)隐藏层与(当前)隐藏层的权值矩阵16行16列,取值区间为[-1, 1),使用区间内随机数初始化
    synapse_h = 2 * np.random.random((hidden_dim, hidden_dim)) - 1
    # 上面三个矩阵更新时的缓冲矩阵
    synapse_0_update = np.zeros_like(synapse_0)
    synapse_1_update = np.zeros_like(synapse_1)
    synapse_h_update = np.zeros_like(synapse_h)

    # 做一万次迭代
    for j in range(10000):
        # 针对其中一次:
        # 生成一个简单的加法问题(a + b = c, a < max / 2, b < max/2, c<max)
        a_int = np.random.randint(largest_number / 2)
        a = int2binary[a_int]

        b_int = np.random.randint(largest_number / 2)
        b = int2binary[b_int]

        # 根据随机获得的a_int, a_int, 计算c_int, 进而获得输出正确情况下的二进制c
        c_int = a_int + b_int
        c = int2binary[c_int]

        # 初始化一个二进制数组,保存a+b的预测值
        d = np.zeros_like(c)

        # 重置误差值
        overallError = 0

        # 记录layer_2导数值
        layer_2_deltas = list()
        # 记录layer_1_values
        layer_1_values = list()
        # 全为0的数组初始化layer_1_values
        layer_1_values.append(np.zeros(hidden_dim))

        # 遍历a,b(8位二进制数组)的每一位
        for position in range(binary_dim):
            # 生成输入和输出,X: a b的同一位, y: c的同一位, 从最右边一位开始
            X = np.array([[a[binary_dim - position - 1], b[binary_dim - position - 1]]])
            y = np.array([[c[binary_dim - position - 1]]]).T

            # 隐藏层 (input ~+ prev_hidden)
            # 这里(1, 2) * (2, 16) + (16,) * (16, 16) = (1, 16) + (16,) = (1, 16), 然后sigmoid((1, 16)) = (1, 16)
            layer_1 = sigmoid(np.dot(X, synapse_0) + np.dot(layer_1_values[-1], synapse_h))

            # 输出层 (new binary representation)
            # (1,16) * (16, 1) = (1,1)
            layer_2 = sigmoid(np.dot(layer_1, synapse_1))

            # 预测值与实际值的误差
            layer_2_error = y - layer_2 # (1,1)
            layer_2_deltas.append((layer_2_error) * sigmoid_out_to_derivative(layer_2)) # ???
            overallError += np.abs(layer_2_error[0]) # 误差之和,维度为(1,)

            d[binary_dim - position - 1] = np.round(layer_2[0][0]) # 输出的预测值(一个进制位)

            layer_1_values.append(copy.deepcopy(layer_1)) # 将隐藏层保存

        future_layer_1_delta = np.zeros(hidden_dim)
        for position in range(binary_dim):
            X = np.array([[a[position], b[position]]])
            layer_1 = layer_1_values[-position - 1]
            prev_layer_1 = layer_1_values[-position - 2]

            layer_2_delta = layer_2_deltas[-position - 1]
            layer_1_delta = (future_layer_1_delta.dot(synapse_h.T) + layer_2_delta
                             .dot(synapse_1.T)) * sigmoid_out_to_derivative(layer_1)
            synapse_1_update += np.atleast_2d(layer_1).T.dot(layer_2_delta)
            synapse_h_update += np.atleast_2d(prev_layer_1).T.dot(layer_1_delta)
            synapse_0_update += X.T.dot(layer_1_delta)
            future_layer_1_delta = layer_1_delta

        synapse_0 += synapse_0_update * alpha
        synapse_1 += synapse_1_update * alpha
        synapse_h += synapse_h_update * alpha
        synapse_0_update = 0
        synapse_1_update = 0
        synapse_h_update = 0

        if (j % 1000 == 0):
            print('Error:%s' % str(overallError))
            print("Pred:%s" % str(d))
            print("True:%s" % str(c))
            out = 0
            for index, x in enumerate(reversed(d)):
                out += x * pow(2, index)
            print("%s + %s = %s" % (str(a_int), str(b_int), str(out)))
            print("-" * 50)
            print(synapse_0)
            print(synapse_1)
            print(synapse_h)
            print("-x" * 50)

    end = time()
    print('耗时%.2f' % (end - start))


if __name__ == '__main__':
    main()

使用tensorflow实现(python3.7+tensorflow2.0):

# -- coding: utf-8 --

import numpy as np
from matplotlib import pyplot as plt
import tensorflow as tf
from tensorflow.keras import layers, models, Sequential

global binary_dim, largest_number
binary_dim = 8
largest_number = pow(2, binary_dim)


# binary = np.unpackbits(np.array([np.arange(largest_number)], dtype=np.uint8).T, axis=1)
# for i in range(largest_number):
#     int2binary[i] = binary[i]


def main():
    # X = np.random.randint(0, largest_number / 2, 4000).reshape(-1, 2)
    # np.save("X", X)
    X = np.load('X.npy')
    X_train_old, X_test_old = X[:1800], X[1800:]
    y = np.sum(X, axis=1).reshape(-1, 1)
    y_train_old, y_test_old = y[:1800], y[1800:]

    # X, y转二进制
    # input: X_train (1800x2x8)
    # output: y_train (1800x8)
    # 单次输入 2x8的X 对应 1x8的y
    X = np.unpackbits(X.astype(np.uint8), axis=1).reshape(-1, 2, 8).astype(np.float32)
    X_train, X_test = X[:1800], X[1800:]
    y = np.unpackbits(y.astype(np.uint8), axis=1).reshape(-1, 8).astype(np.float32)
    y_train, y_test = y[:1800], y[1800:]

    # 创建模型
    model = Sequential()
    # LSTM: 记忆相邻两组数据
    model.add(layers.LSTM(16, activation='relu', input_shape=(2, 8)))
    model.add(layers.Dense(8, activation='relu'))
    model.compile(loss='mse', optimizer='adam')
    h = model.fit(X_train, y_train, batch_size=20, epochs=1000)

    # 绘制loss的变化
    plt.figure(figsize=(16,2))
    plt.plot(h.history['loss'])
    plt.show()

    model.save('lstm_model.h5')

    model = models.load_model('lstm_model.h5')
    cc = pow(2, np.arange(8))[::-1]
    y_test_predict = np.round(model.predict(X_test))
    # 将model预测值二级制转十进制
    y_test_predict = np.dot(y_test_predict, cc).reshape(-1, 1)
    print(X_test_old)
    print(y_test_old)
    print(y_test_predict)
    print(y_test_predict - y_test_old)
    # errorAll = np.sum(np.abs(y_test_predict - y_test_old)) / 200
    # print(errorAll)
    print('finish.')


if __name__ == '__main__':
    main()

损失函数loss:


Figure_1.png
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,367评论 6 512
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,959评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,750评论 0 357
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,226评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,252评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,975评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,592评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,497评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,027评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,147评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,274评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,953评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,623评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,143评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,260评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,607评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,271评论 2 358

推荐阅读更多精彩内容