TensorFlow 模型建立与训练

看一下你的model的predict方法最后有没有一句

return tf.argmax(q_values, axis=-1)

如果没有的话需要加上。我之前手滑写错行号结果这一句没有显示,现在已修正。

或者直接到这里获取完整源代码: tensorflow-handbook/qlearning.py at master · snowkylin/tensorflow-handbook · GitHub

谢谢,运行成功了 :smiling_face_with_three_hearts:

1 Like

你好,我在run你的linear模型的时候,遇到IDE报错:‘Linear’ object is not callable
然后结果是AttributeError: ‘Linear’ object has no attribute ‘dense’,请问是什么问题呢?


这里的CNN示例图显示了一个全连接层有64个神经元,是不是和示例代码的不符,示例代码中没看到64个神经元的存在?

你这么一说的话,确实……你可以自己加一层看看效果会不会更好一些

请参考本帖说明,提供TensorFlow 版本和完整的最小可运行程序代码

非常感谢回复

你好,关于多层感知机例子中有个问题请教,第一个全连接层
self.dense1 = tf.keras.layers.Dense(units=100, activation=tf.nn.relu)
这个输出维度100是依据什么确定的?

另外还有一个问题,关于多层感知机例子中损失函数这个地方
loss = tf.keras.losses.sparse_categorical_crossentropy(y_true=y, y_pred=y_pred)
loss = tf.reduce_mean(loss)
这两句为什么不能直接使用 loss=tf.reduce_mean(tf.square(y_pred - y)) [假设不考虑训练效果的情况下]
我改成这个后执行报错“Invalid argument: required broadcastable shapes at loc(unknown)”

您好 RNN模型中loss函数一直保持在3左右,在model调用中将training = True启用也无效.相应代码:

import tensorflow as tf
class DataLoader():
def init(self):
path = tf.keras.utils.get_file(‘nietzsche.txt’,
origin=‘https://s3.amazonaws.com/text-datasets/nietzsche.txt’) # 读取尼采的文章
with open(path, encoding=‘utf-8’) as f:
self.raw_text = f.read().lower() #将文章读入raw_text,转换为小写
self.chars = sorted(list(set(self.raw_text))) #将文章中所有字符排序 (取字符集)
self.char_indices = dict((c, i) for i, c in enumerate(self.chars)) #char - number
self.indices_char = dict((i, c) for i, c in enumerate(self.chars)) #number - char
self.text = [self.char_indices[c] for c in self.raw_text] #将尼采的文章raw_text 转化为数字编码

def get_batch(self, seq_length, batch_size):                     # batch_size: 取多少个句子   seq_length: 每个句子有多长
    seq = []                                 #列表,元素也是列表,是句子
    next_char = []                           #列表,元素是数字编码,对应seq每个元素后面跟着的数字编码
    for i in range(batch_size):
        index = np.random.randint(0, len(self.text) - seq_length)    #在数字编码形式的文章内部取一随机数作为start
        seq.append(self.text[index:index+seq_length])                #从start位置开始取seq_length长度的列表作为seq的一个元素
        next_char.append(self.text[index+seq_length])                #seq每个元素(列表)后面的一个字符对应 next_char
    return np.array(seq), np.array(next_char)       # author:[batch_size, seq_length], [num_batch]
#返回[batch_size,seq_length]、[batch_size,1]大小的nparray,即一次读入batch_size大小的数据,以及next_char

class RNN(tf.keras.Model):
def init(self, num_chars, batch_size, seq_length): #num_chars 应该为最后想生成的语句长度? 错。是文章中有的不同字符的数量。
super().init()
self.num_chars = num_chars
self.seq_length = seq_length
self.batch_size = batch_size
self.cell = tf.keras.layers.LSTMCell(units=256)
self.dense = tf.keras.layers.Dense(units=self.num_chars)

def call(self, inputs, from_logits=False):
    inputs = tf.one_hot(inputs, depth=self.num_chars)       # 从二维变为三维:[batch_size, seq_length, num_chars]
    state = self.cell.get_initial_state(batch_size=self.batch_size, dtype=tf.float32)   # 获得 RNN 的初始状态
    for t in range(self.seq_length):
        output, state = self.cell(inputs[:, t, :], state)   # 通过当前输入和前一时刻的状态,得到输出和当前时刻的状态 #和layers.LSTMCell函数有关,不熟悉。
    logits = self.dense(output)
    if from_logits:                     # from_logits 参数控制输出是否通过 softmax 函数进行归一化
        return logits
    else:
        return tf.nn.softmax(logits)

def predict(self, inputs, temperature=1.):
    batch_size, _ = tf.shape(inputs)
    logits = self(inputs, from_logits=True)                         # 调用训练好的RNN模型,预测下一个字符的概率分布
    prob = tf.nn.softmax(logits / temperature).numpy()              # 使用带 temperature 参数的 softmax 函数获得归一化的概率分布值
    return np.array([np.random.choice(self.num_chars, p=prob[i, :]) # 使用 np.random.choice 函数,
                     for i in range(batch_size.numpy())])           # 在预测的概率分布 prob 上进行随机取样

num_batches = 1000
seq_length = 40
batch_size = 50
learning_rate = 1e-3

data_loader = DataLoader()
model = RNN(num_chars=len(data_loader.chars), batch_size=batch_size, seq_length=seq_length)
optimizer = tf.keras.optimizers.Adam(learning_rate=learning_rate)
for batch_index in range(num_batches):
X, y = data_loader.get_batch(seq_length, batch_size)
with tf.GradientTape() as tape:
y_pred = model(X,training = True) #此处对实例化的model,开始调用call函数。
loss = tf.keras.losses.sparse_categorical_crossentropy(y_true=y, y_pred=y_pred)
loss = tf.reduce_mean(loss)
print(“batch %d: loss %f” % (batch_index, loss.numpy()))
grads = tape.gradient(loss, model.variables)
optimizer.apply_gradients(grads_and_vars=zip(grads, model.variables))

刚刚调用了您在github上的RNN代码https://github.com/snowkylin/tensorflow-handbook/blob/master/source/_static/code/zh/model/text_generation/rnn.py,部分结果如下

index = np.random.randint(0, self.num_train_data, batch_size)
return self.train_data[index, :], self.train_label[index]
博主你好,这边index的返回值不是一个list,下面的return该怎么理解

虽然不是list,但是是一个numpy array,比如np.random.randint(0, 100, 10)的结果可以是

array([45, 17, 86, 84, 15, 32, 10, 24, 37, 30])

和list也差不多,详细可以参考 Indexing on ndarrays — NumPy v2.0.dev0 Manual

这里的交叉熵计算的y_ture是label,y_pred是概率,两个tensor的形状不一样,不能直接做减法。如果要让你这里的y_pred - y成立,要先对y做一个tf.one_hot,即

y_true=tf.one_hot(y, depth=tf.shape(y_pred)[-1])

详细可以参考 https://tf.wiki/zh_hans/basic/models.html#mlp 里面“交叉熵”部分的注解。

加大 num_batchesbatch_size 试试,效果应该会更好(不过训练会花更长时间)。

维度是根据经验选的,这个值你可以自己设一个合适的(比较自由,不过别太小或太大)

请问这个报错是什么问题呀 Unresolved reference ‘MLP’ 下面是我按照书上敲得代码

import numpy as np
import tensorflow as tf
#数据获取及预处理
class MNISTLoader():
    def __init__(self):
        mnist=tf.keras.datasets.mnist
        (self.train_data,self.train_lable),(self.test_data,self.test_lable)=mnist.load_data()
        self.train_data=np.expand_dims(self.train_data.astype(np.float32)/255.0,axis=-1)
        self.test_data=np.expand_dims(self.test_data.astype(np.float32)/255.0,axis=-1)
        self.train_lable=self.train_lable.astype(np.int32)
        self.test_lable=self.test_lable.astype(np.int32)
        self.num_train_data,self.num_test_data=self.train_data.shape[0],self.test_data.shape[0]
    def get_batch(self,batch_size):
        index=np.random.randint(0,np.shape(self.train_data)[0],batch_size)
        return self.train_data[index,:],self.train_lable[index]
    #模型的构建
class MLP(tf.keras.Model):
    def __init__(self):
        super().__init__()
        self.flatten=tf.keras.layers.Flatten()
        self.dense1=tf.keras.layers.Dense(unit=100,activation=tf.nn.relu)
        self.dense2=tf.keras.layers.Dense(unit=10)
    def call(self,inputs):
        x=self.flatten(inputs)
        x=self.dense1(x)
        x=self.dense2(x)
        output=tf.nn.softmax(x)
        return output
    #模型的训练
    num_epochs=5
    batch_size=50
    learning_rate=0.001
    model=MLP()
    data_loader=MNISTLoader()
    optimizer=tf.keras.optimizers.Adam(learning_rate=learning_rate)
    num_batches=int(data_loader.num_train_data//batch_size*num_epochs)
    for batch_index in range(num_batches):
        X,y=data_loader.get_batch(batch_size)
        with tf.GradientTape() as tape:
            y_pred=model(X)
            loss=tf.keras.losses.sparse_categorical_crossentropy(y_true=y,y_pred=y_pred)
            loss=tf.reduce_mean(loss)
            print("batch %d:loss %f"%(batch_index,loss.numpy()))
        grads=tape.gradient(loss,model.variables)
        optimizer.apply_gradients(grads_and_vars=zip(grads,model.variables))
        #模型的评估
        sparse_categorical_accuracy=tf.keras.metrics.SparseCategoricalAccuracy()
        num_batches=int(data_loader.num_test_data//batch_size)
        for batch_index in range(num_batches):
            start_index,end_index=batch_index*batch_size,(batch_index+1)*batch_size
            y_pred=model.predict(data_loader.test_data[start_index:end_index])
            sparse_categorical_accuracy.updata_state(
                y_ture=data_loader.test_lable[start_index:end_index],y_pred=y_pred)
        print("test accuracy:%f"%sparse_categorical_accuracy.result())

您的代码里存在不少拼写错误(例如把units打成了unitupdate_state打成了updata_state)和缩进错误(“模型的训练”后面的代码不应该在MLP类里)。如果确实要运行示例代码,建议直接复制网站上的代码,以及可以参考 runoob 网站的 Python 3 教程廖雪峰的 Python 教程 学习巩固一下Python基础知识。

新手让您见笑了,我会去巩固下基础知识的,非常感谢您的帮助。

遇到同样问题,loss不收敛,请问解决了吗?