如果一个张量的形状是 (a, b, ... n, n+1, ... m) ,另一个张量的形状是 (n, n+1, ... m) ,那么你通常可以利用广播对它们做两个张量之间的逐元素运算。广播操作会自动应用于从 a 到 n-1 的轴
在 Numpy、Keras、Theano 和 TensorFlow 中,都是用 * 实现逐元素乘积,在 Numpy 和 Keras 中,都是用标准的 dot 运算符来实现点积
a = np.array([1, 2]) b = np.array([[5], [6]]) # 输出[17] print(a.dot(b))张量变形是指改变张量的行和列,以得到想要的形状。变形后的张量的元素总个数与初始张量相同
a = np.array([[0, 1], [2, 3], [4, 5]]) print(a) print("after reshape: \n", a.reshape((2, 3)))输出
[[0 1] [2 3] [4 5]] after reshape: [[0 1 2] [3 4 5]]转置 np.transpose(x)
SGD(stochastic gradient descent) -- 随机梯度下降
不同的张量格式与不同的数据处理类型需要用到不同的层,简单的向量数据保存在形状为 (samples, features) 的 2D 张量中,通常用密集连接层[densely connected layer,也叫全连接层(fully connected layer)或密集层(dense layer),对应于 Keras 的 Dense 类]来处理。序列数据保存在形状为 (samples, timesteps, features) 的 3D 张量中,通常用循环层(recurrent layer,比如 Keras 的 LSTM 层)来处理。图像数据保存在 4D 张量中,通常用二维卷积层(Keras 的 Conv2D )来处理
Keras框架具有层兼容性,具体指的是每一层只接受特定形状的输入张量,并返回特定形状的输出张量
layer = layers.Dense(32, input_shape=(784,))创建了一个层,只接受第一个维度大小为 784 的 2D 张量作为输入。这个层将返回一个张量,第一个维度的大小变成了 32 因此,这个层后面只能连接一个接受 32 维向量作为输入的层,使用 Keras 时,你无须担心兼容性,因为向模型中添加的层都会自动匹配输入层的形状,下一次层可以写为
model.add(layers.Dense(32))它可以自动推导出输入形状等于上一层的输出形状
具有多个输出的神经网络可能具有多个损失函数(每个输出对应一个损失函数)。但是,梯度下降过程必须基于单个标量损失值。因此,对于具有多个损失函数的网络,需要将所有损失函数取平均,变为一个标量值
一个 Keras 工作流程
定义训练数据: 输入张量和目标张量
定义层组成的网络(或模型),将输入映射到目标
配置学习过程:选择损失函数、优化器和需要监控的指标
调用模型的 fit 方法在训练数据上进行迭代
定义模型有两种方法:
一种是使用 Sequential 类(仅用于层的线性堆叠,这是目前最常见的网络架构)
另一种是函数式 API(functional API,用于层组成的有向无环图,让你可以构建任意形式的架构)
Sequential 类定义两层模型
函数式 API 定义的相同模型
input_tensor = layers.Input(shape=(784,)) x = layers.Dense(32, activation='relu')(input_tensor) output_tensor = layers.Dense(10, activation='softmax')(x) model = models.Model(inputs=input_tensor, outputs=output_tensor)以下学习根据电影评论的文字内容将其划分为正面或负面
使用 IMDB 数据集,数据集被分为用于训练的 25 000 条评论与用于测试的 25 000 条评论,训练集和测试集都包含 50% 的正面评论和 50% 的负面评论
其中,数据集中的labels 都是 0 和 1 组成的列表,0代表负面(negative),1 代表正面(positive)
你不能将整数序列直接输入神经网络。你需要将列表转换为张量。转换方法有以下两种
填充列表,使其具有相同的长度,再将列表转换成形状为 (samples, word_indices)的整数张量,然后网络第一层使用能处理这种整数张量的层
对列表进行 one-hot 编码,将其转换为 0 和 1 组成的向量。举个例子,序列 [3, 5] 将会被转换为 10 000 维向量,只有索引为 3 和 5 的元素是 1,其余元素都是 0,然后网络第一层可以用 Dense 层,它能够处理浮点数向量数据
训练代码
from keras.datasets import imdb import os import numpy as np from keras import models from keras import layers import matplotlib.pyplot as plt # 将整数序列编码为二进制矩阵 def vectorize_sequences(sequences, dimension=10000): results = np.zeros((len(sequences), dimension)) for i, sequence in enumerate(sequences): # results[i] 的指定索引设为 1 results[i, sequence] = 1 return results data_url_base = "/home/fan/dataset" # 下载数据且只保留出现频率最高的前10000个单词 (train_data, train_labels), (test_data, test_labels) = imdb.load_data(num_words=10000, path=os.path.join(data_url_base, "imdb.npz")) # 将某条评论迅速解码为英文单词 # word_index 是一个将单词映射为整数索引的字典 word_index = imdb.get_word_index(path=os.path.join(data_url_base, "imdb_word_index.json")) # 将整数索引映射为单词 reverse_word_index = dict([(value, key) for (key, value) in word_index.items()]) # 索引减去了 3,因为 0、1、2是为“padding”(填充)、 # “start of sequence”(序列开始)、“unknown”(未知词)分别保留的索引 decoded_review = ' '.join([reverse_word_index.get(i - 3, '?') for i in train_data[0]]) print(decoded_review) # 将数据向量化 x_train = vectorize_sequences(train_data) x_test = vectorize_sequences(test_data) # 将标签向量化 y_train = np.asarray(train_labels).astype('float32') y_test = np.asarray(test_labels).astype('float32') # 设计网络 # 两个中间层,每层都有 16 个隐藏单元 # 第三层输出一个标量,预测当前评论的情感 # 中间层使用 relu 作为激活函数,最后一层使用 sigmoid 激活以输出一个 0~1 范围内的概率值 model = models.Sequential() model.add(layers.Dense(16, activation='relu', input_shape=(10000,))) model.add(layers.Dense(16, activation='relu')) model.add(layers.Dense(1, activation='sigmoid')) # 模型编译 # binary_crossentropy二元交叉熵 model.compile(optimizer='rmsprop', loss='binary_crossentropy', metrics=['acc']) # 留出验证集 x_val = x_train[:10000] partial_x_train = x_train[10000:] y_val = y_train[:10000] partial_y_train = y_train[10000:] history = model.fit(partial_x_train, partial_y_train, epochs=20, batch_size=512, validation_data=(x_val, y_val)) # 得到训练过程中的所有数据 history_dict = history.history print(history_dict.keys()) # 绘制训练损失和验证损失 loss_values = history_dict['loss'] val_loss_values = history_dict['val_loss'] epochs = range(1, len(loss_values) + 1) # 'bo' 蓝色圆点 plt.plot(epochs, loss_values, 'bo', label='Training loss') # 'b' 蓝色实线 plt.plot(epochs, val_loss_values, 'b', label='Validation loss') plt.title("Training and Validation loss") plt.xlabel('Epochs') plt.legend() plt.show() # 绘制训练精度和验证精度 # plt.clf() 清空图像 acc = history_dict['acc'] val_acc = history_dict['val_acc'] plt.plot(epochs, acc, 'bo', label='Training acc') plt.plot(epochs, val_acc, 'b', label='Validation acc') plt.title('Training and validation accuracy') plt.xlabel('Epochs') plt.ylabel('Accuracy') plt.legend() plt.show()