TensorFlow入门-简单RNN

本文介绍了一个基于TensorFlow框架实现的RNN模型,该模型用于预测具有一定依赖关系的二进制序列。输入数据为随机生成的二进制序列,输出数据则根据输入序列中特定位置的值来确定。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在深度学习的路上,从头开始了解一下各项技术。本人是DL小白,连续记录我自己看的一些东西,大家可以互相交流。

之前写过一些关于深度学习的简单概念,最近这段时间会看一些代码相关的东西。

本文参考:

https://github.com/lawlite19/Blog-Back-Up/blob/master/code/rnn/rnn_implement.py

一、前言

RNN擅长于处理序列化的问题,本片是基于TensorFlow框架的实现,用于处理一个二进制序列的预测。

二、数据描述

  • 输入数据X二进制的一串序列, 在t时刻,有50%的概率是150%的概率是0,比如:X=[1,1,0,0,1,0.....]

  • 输出数据Y
    • 在时刻t50%的概率是150%的概率是0
    • 如果Xt−3是1,则Yt 100%1(增加50%);
    • 如果Xt−8是1,则Yt 25%1(减少25%);
      • 所以如果Xt−3和Xt−8都是1,则Yt 50%+50%-25%=75%的概率是1

针对于如上数据,各个时间步之间有依赖关系,但是也存在随机性,可以模拟语言处理的简单情况。

具体的实现步骤和注释见具体代码。

三、代码实现

import numpy as np
import tensorflow as tf
from tensorflow.python import debug as tf_debug
import matplotlib.pyplot as plt

#hyperparameters
#只能记忆10步,误差只往前传播10步,至少8步才能学到第二个依赖
#每10个RNN cell一个截断
num_steps = 10
#每200个训练样本一批
batch_size = 200
#最后分为2类
num_classes = 2
#RNN中的unit个数-16个
state_size = 16
learning_rate = 0.1

#生成数据
#输入数据X是二进制的一串序列, 在t时刻,有50%的概率是1,50%的概率是0,比如:X=[1,1,0,0,1,0.....]
#输出数据Y:
#在时刻t,50%的概率是1,50%的概率是0;
#如果Xt−3是1,则Yt 100%是1(增加50%);
#如果Xt−8是1,则Yt 25%是1(减少25%);
#所以如果Xt−3和Xt−8都是1,则Yt 50%+50%-25%=75%的概率是1
#所以,输出数据是有两个依赖关系的
def gen_data(size=1000000):
    #返回一个列表的随即项
    #生成size大小个数列
    X = np.array(np.random.choice(2, size=(size,)))
    Y = []
    #根据对应X生成Y
    for i in range(size):
        threshold = 0.5
        if X[i-3] == 1:
            threshold += 0.5
        if X[i-8] == 1:
            threshold -= 0.25
        if np.random.rand() > threshold:
            Y.append(0)
        else:
            Y.append(1)
    return X, np.array(Y)

#生成batch数据,raw_data是全部数据
#实现从全部数据,到(x, y)的转化
def gen_batch(raw_data, batch_size, num_steps):
    raw_x, raw_y = raw_data
    #数据总长度
    data_length = len(raw_x) #1000000
    #每个batch的长度,一共1000000个数据,batch_size为200,分成5000个200大小的批
    batch_patition_length = data_length // batch_size  # 5000
    #先用0填充矩阵,初始化
    data_x = np.zeros([batch_size, batch_patition_length], dtype=np.int32)  # (200, 5000)
    data_y = np.zeros([batch_size, batch_patition_length], dtype=np.int32)  # (200, 5000)
    #填充内容到对应位置,生成data_x, data_y
    for i in range(batch_size):
        data_x[i] = raw_x[batch_patition_length*i: batch_patition_length*(i+1)]#raw_x[start: end]从开始到最后分开
        data_y[i] = raw_y[batch_patition_length*i: batch_patition_length*(i+1)]
        epoch_size = batch_patition_length // num_steps  # 每一个RNN cell的大小
    #抽取data_x, data_y,生成x,y的生成器
    for i in range(epoch_size):  # 抽取epoch_size 个数据,数据生成器
        x = data_x[:, i * num_steps: (i+1) * num_steps]  # (200, 5)
        y = data_y[:, i * num_steps: (i+1) * num_steps]
        yield (x, y)

def gen_epochs(n, num_steps):
    for i in range(n):
        yield gen_batch(gen_data(), batch_size, num_steps)

#创建placeholder
x = tf.placeholder(tf.int32, [batch_size, num_steps], name = 'x')
y = tf.placeholder(tf.int32, [batch_size, num_steps], name = 'y')
#a向量,初始化为0向量(200, 16)
init_state = tf.zeros([batch_size, state_size])
#RNN输入
x_one_hot = tf.one_hot(x, num_classes)
#unstack()矩阵分解的函数
rnn_inputs = tf.unstack(x_one_hot, axis=1)

#定义RNN的cell
"""""
name_scope 和 variable_scope的用法,类似与tf.Variable,也是用于定义变量
"""""
#创建rnn_cell的参数
with tf.variable_scope('rnn_cell'):
    W = tf.get_variable('W', [num_classes + state_size, state_size])
    b = tf.get_variable('b', [state_size], initializer=tf.constant_initializer(0.0))
#创建rnn_cell
def rnn_cell(rnn_input, state):
    #取出参数
    with tf.variable_scope('rnn_cell', reuse=True):
        W = tf.get_variable('W', [num_classes + state_size, state_size])
        b = tf.get_variable('b', [state_size], initializer=tf.constant_initializer(0.0))
    return tf.tanh(tf.matmul(tf.concat([rnn_input, state], 1), W) + b)
#把rnn cell添加进计算图
state = init_state
rnn_outputs = []
for rnn_input in rnn_inputs:
    state = rnn_cell(rnn_input, state)
    rnn_outputs.append(state)
final_state = rnn_outputs[-1]  # [-1]最后一个元素

#预测
#创建softmax的参数
with tf.variable_scope('softmax'):
    W = tf.get_variable('W', [state_size, num_classes])
    b = tf.get_variable('b', [num_classes], initializer=tf.constant_initializer(0.0))
#输入值,即为rnn的输出值
logits = [tf.matmul(rnn_output, W) + b for rnn_output in rnn_outputs]
predictions = [tf.nn.softmax(logit) for logit in logits]
#y为(200, 5)拆分为(200, ) * 5
y_as_list = tf.unstack(y, num=num_steps, axis=1)

#计算损失和优化
losses = [tf.nn.sparse_softmax_cross_entropy_with_logits(labels=label, logits=logit) for logit, label in zip(logits, y_as_list)]
total_loss = tf.reduce_mean(losses)
train_step = tf.train.AdagradOptimizer(learning_rate).minimize(total_loss)

#构建RNN网络训练
def train_rnn(num_epochs, num_steps, state_size = 16, verbose = True):
    with tf.Session() as sess:
        sess.run(tf.global_variables_initializer())
        #训练损失统计参数
        training_losses = []
        # yield gen_batch(gen_data(), batch_size, num_steps)
        #enumerate()将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列,同时列出数据和数据下标,一般用在 for 循环当中
        #idx: 每一截断的序列号, epoch: 截断的数据
        for idx, epoch in enumerate(gen_epochs(num_epochs, num_steps)):
            training_loss = 0
            #初始化状态向量为0向量,形状为(200, 16)
            training_state = np.zeros((batch_size, state_size))
            #verbose是否打印
            if verbose:
                print('\nepoch', idx)
            for step, (X, Y) in enumerate(epoch):
                tr_losses, training_loss_, training_state, _ = \
                    sess.run([losses, total_loss, final_state, train_step],
                             feed_dict={x: X, y: Y, init_state: training_state})
                training_loss += training_loss_
                if step % 100 == 0 and step > 0:
                    if verbose:
                        print('第 {0} 步的平均损失 {1}'.format(step, training_loss / 100))
                    training_losses.append(training_loss / 100)
                    training_loss = 0
    return training_losses


training_losses = train_rnn(num_epochs=5, num_steps=num_steps, state_size=state_size)
print(training_losses[0])
plt.plot(training_losses)
plt.show()


 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值