深度学习入门

文章目录

        • 理论基础
          • 张量:矩阵任意维度的推广
          • 样本批量
          • 神经网络的原理:张量运算
          • 深度学习的几何解释
          • 神经网络的核心:梯度优化
        • 神经网络的组件
          • 层:深度学习的基础组件
            • 激活函数:
            • 数据向量化
          • 模型:层构成的网络
          • 损失函数与优化器
        • 第一个神经网络:MNIST数字识别
          • 1.导库
          • 2.建立网络架构
          • 3.编译步骤
          • 4.数据处理
          • 5.开始训练
        • 第二个神经网络:IMDB影评情感分析(二分类问题)
          • 1.加载数据集
            • 数据集解码
          • 2.数据预处理
          • 3.构建网络
          • 4.模型的编译
          • 5.模型的验证
          • 6.模型的预测
        • 第三个神经网络:路透社数据集(多分类问题)
          • 1.加载数据集
          • 2.数据预处理
          • 3.构建网络
          • 4.模型编译
          • 5.模型的验证
          • 6.模型的预测
            • 处理标签的另一种方法
        • 第四个神经网络:波士顿房价预测(回归问题)
        • 1.加载数据集
          • 2.数据预处理
          • 3.构建网络
          • 4.验证网络
        • 总结

理论基础

张量:矩阵任意维度的推广
x.ndim  #查看张量的形状
x.dtype #查看张量的属性

3d张量:三维数组

3d向量:向量中有三个元素

样本批量

深度学习中所有数据张量的第一个轴(0轴)都是样本轴,存放着样本名(个人理解)

神经网络的原理:张量运算
  1. 逐元素运算
  2. 广播运算
  3. 张量点积
  4. 张量变形
深度学习的几何解释

为复杂,高度折叠的数据流找到简洁的表示。

与人类展开纸球的策略大致相同。

神经网络的核心:梯度优化

每个神经层都用下述方法对输入数据进行变换:
o u t p u t = r e l u ( d o t ( w , i n p u t ) + b ) output=relu(dot(w,input)+b) output=relu(dot(w,input)+b)
w和b都是张量,为改成的属性。被称为层的权重(可训练参数)。

更新权重的方法:梯度(张量运算的导数,是多元函数导数的推广。)

常用:小批量随机梯度下降(SGD),其他的变体被称为优化器。

神经网络的组件

层:深度学习的基础组件
激活函数:
  • relu函数可以将所有负值归0
  • sigmoid函数可以将任意值‘压缩’到[0,1]区间内,其输出值可以看作概率值。
  • softmax函数:可以输出不同输出类别上的概率分布,每个类别累加起来的概率综合为1
数据向量化
  1. 填充列表,使其长度相等,再将列表转换形状为(samples,word_indices)的整数张量。然后网络第一层使用能够处理这种整数数量的层(embedding层,这样能减少内存的占用)。
  2. 对列表进行one-hot编码
模型:层构成的网络
损失函数与优化器

损失函数:在训练过程中需要将其最小化。他能衡量当前任务是否已经完成。

网络输出是一个概率值,最好使用binary_crossentropy(二元交叉熵),也可以使用mean_squared_error(均方误差)。

优化器:决定如何基于损失函数对网络进行更新。她执行的是随机梯度下降(SGD)的某个变体。

优化器和损失函数均可以自定义。

第一个神经网络:MNIST数字识别

1.导库
from tensorflow.keras.datasets import mnist
(train_images, train_labels), (test_images, test_labels) = mnist.load_data() #导入数据

2.建立网络架构

数据结构的核心组建是层,通过几个层来实现数据的筛选。

Dense层:全连接层

activation:激活函数,为了让训练过程变得非线性。

from tensorflow import keras
from tensorflow.keras import layers
model = keras.Sequential([
    layers.Dense(512, activation="relu"),   #本层为dense全连接层,拥有512个隐藏的神经元,激活函数为relu,
    layers.Dense(10, activation="softmax")  #本层为dense全连接层,拥有10个输出单元,会返回一个由10个概率值(总和为1)组成的数组,每个概率值表示当前数字图像属于10个数字类别中某一个的概率。
])
3.编译步骤

优化器(optimizer)

损失函数(loss)

需要监控的指标(metric)

model.compile(optimizer="有人说,看懂了大话西游,你就明白了爱情是什么,明白了又怎样,放不开的还是放不开",
              loss="sparse_categorical_crossentropy",
              metrics=["accuracy"])
4.数据处理
#对训练集做处理
train_images = train_images.reshape((60000, 28 * 28))
train_images = train_images.astype("float32") / 255   #将数据归一化,会使模型训练得更好
test_images = test_images.reshape((10000, 28 * 28))
test_images = test_images.astype("float32") / 255

#对标签进行处理
from keras.utils import to_categorical
train_labels = to_categorical(train_labels)
test_labels = to_categorical(test_labels)
5.开始训练

训练批次:epochs

数据批量:batch_size

model.fit(train_images,train_labels,epochs=5,batch_size=128)

第二个神经网络:IMDB影评情感分析(二分类问题)

IMDB数据集:50 000条两极分化的电影评论。

1.加载数据集

train_data是由每个评论组成,每条评论是由单词索引组成的列表

from tensorflow.keras.datasets import imdb
(train_data, train_labels), (test_data, test_labels) = imdb.load_data(num_words=10000)#选取前10000个最常出现的单词,便于处理
数据集解码
word_index = imdb.get_word_index()        #加载IMDB内置的单词字典
reverse_word_index = dict([(value, key) for (key, value) in word_index.items()])     #构建解码字典
decoded_review = " ".join([reverse_word_index.get(i - 3, "?") for i in train_data[0]])	#进行解码,i-3是因为0,1,2是为(填充,序列的开始,未知词)分别保留的序列
2.数据预处理

(数据向量化)

  1. 填充列表,使其长度相等,再将列表转换形状为(samples,word_indices)的整数张量。然后网络第一层使用能够处理这种整数数量的层(embedding层,这样能减少内存的占用)。
  2. 对列表进行one-hot编码
#将数据编码独热化
import numpy as np
def vectorize_sequences(sequences, dimension=10000):
    results = np.zeros((len(sequences), dimension))
    for i, sequence in enumerate(sequences):
        for j in sequence:
            results[i, j] = 1.
    return results
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")
3.构建网络

对dense层的堆叠,需要确定以下两个关键架构

  1. 网络有多少层
  2. 每层有多少个隐藏单元

激活函数:

relu函数可以将所有负值归0

sigmoid函数可以将任意值‘压缩’到[0,1]区间内,其输出值可以看作概率值。

from tensorflow import keras
from tensorflow.keras import layers

model = keras.Sequential()
model.add(layers.Dense(16, activation="relu"))
model.add(layers.Dense(16, activation="relu"))
model.add(layers.Dense(1, activation="rsigmoid"))
4.模型的编译
model.compile(optimizer="rmsprop",
              loss="binary_crossentropy",
              metrics=["accuracy"])
5.模型的验证
#1.留出验证集
x_val = x_train[:10000]
partial_x_train = x_train[10000:]
y_val = y_train[:10000]
partial_y_train = y_train[10000:]
#2.训练模型
history = model.fit(partial_x_train,
                    partial_y_train,
                    epochs=20,
                    batch_size=512,
                    validation_data=(x_val, y_val))
#3.结果的查看
#调用model.fit()会返回一个history对象,这对象有个history字典
history_dict = history.history
history_dict.keys()

#4.绘制训练损失和验证损失
import matplotlib.pyplot as plt
history_dict = history.history
loss_values = history_dict["loss"]
val_loss_values = history_dict["val_loss"]
epochs = range(1, len(loss_values) + 1)
plt.plot(epochs, loss_values, "bo", label="Training loss")
plt.plot(epochs, val_loss_values, "b", label="Validation loss")
plt.title("Training and validation loss")
plt.xlabel("Epochs")
plt.ylabel("Loss")
plt.legend()
plt.show()

#5.绘制训练精度和验证精度
import matplotlib.pyplot as plt
acc = history_dict["accuracy"]
val_acc = history_dict["val_accuracy"]
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()
6.模型的预测
model.predict(x_test)

第三个神经网络:路透社数据集(多分类问题)

路透社数据集包含46个新闻主题,每个主题至少有10个样本。

1.加载数据集
from tensorflow.keras.datasets import reuters
(train_data, train_labels), (test_data, test_labels) = reuters.load_data(num_words=10000)


#数据集解码
word_index = reuters.get_word_index()
reverse_word_index = dict([(value, key) for (key, value) in word_index.items()])
decoded_newswire = " ".join([reverse_word_index.get(i - 3, "?") for i in
    train_data[0]])
2.数据预处理
#将数据向量化
x_train = vectorize_sequences(train_data)
x_test = vectorize_sequences(test_data)
#将标签向量化
#方法1
def to_one_hot(labels, dimension=46):
    results = np.zeros((len(labels), dimension))
    for i, label in enumerate(labels):
        results[i, label] = 1.
    return results
y_train = to_one_hot(train_labels)
y_test = to_one_hot(test_labels)

#方法2
from tensorflow.keras.utils import to_categorical
y_train = to_categorical(train_labels)
y_test = to_categorical(test_labels)
3.构建网络

如果要对n个类别进行分类,网络的最后一层应该是大小为n的dense层。

网络的最后一层是大小为46的dense层,前面的层不应该比他更小,因为这样会使部分信息永久丢失。

model = keras.Sequential([
    layers.Dense(64, activation="relu"),
    layers.Dense(64, activation="relu"),
    layers.Dense(46, activation="softmax")
])
4.模型编译

softmax函数:可以输出不同输出类别上的概率分布,每个类别累加起来的概率综合为1

对于多分类问题,最好的损失函数就是categorical_crossentropy(分类交叉熵)。可以衡量两个概率分布之间的距离,这里的两个概率分布分别是网络输出的概率分布和标签的真是分布。通过使两个分布距离达到最小化,使输出结果尽可能接近真是标签。

model.compile(optimizer="rmsprop",
              loss="categorical_crossentropy",
              metrics=["accuracy"])
5.模型的验证
#留出验证集
x_val = x_train[:1000]
partial_x_train = x_train[1000:]
y_val = y_train[:1000]
partial_y_train = y_train[1000:]
#训练模型
history = model.fit(partial_x_train,
                    partial_y_train,
                    epochs=20,
                    batch_size=512,
                    validation_data=(x_val, y_val))
6.模型的预测
predictions = model.predict(x_test)
predictions[0].shape  #每个元素长度都是46
np.sum(predictions[0]) #所有元素总和为1
np.argmax(predictions[0])  #最大的元素就是预测类别,就是概率最大的类别
处理标签的另一种方法

将其转换为整数张量,1-46。

需要改变的是损失函数的选择,需要选择sparse_categorical_crossentropy

第四个神经网络:波士顿房价预测(回归问题)

1.加载数据集

from tensorflow.keras.datasets import boston_housing
(train_data, train_targets), (test_data, test_targets) = boston_housing.load_data()
2.数据预处理
#数据标准化
mean = train_data.mean(axis=0)
train_data -= mean
std = train_data.std(axis=0)
train_data /= std
test_data -= mean
test_data /= std
3.构建网络

由于样本数量很少,我们只使用一个非常小的网络。

一般来说,训练数据越少,过拟合会越严重,我们用较小的网络可以降低过拟合。

网络的最后一层只有一个单元,没有激活,是一个线性层,这就是标量回归的典型设置。

损失函数为MSE均方误差,是回归问题常用的损失函数。

#因为后续操作需要多次用到这个模型,所以用一个函数来构造
def build_model():
    model = keras.Sequential([
        layers.Dense(64, activation="relu"),
        layers.Dense(64, activation="relu"),
        layers.Dense(1)
    ])
    model.compile(optimizer="rmsprop", loss="mse", metrics=["mae"])
    return model
4.验证网络

这里利用了一个新的方法:k折验证法。将数据分为k个区,每组数据分别成为验证集,之后将k次训练集的分数平均起来得到模型的最终分数。

k = 4
num_val_samples = len(train_data) // k
num_epochs = 100
all_scores = []
for i in range(k):
    print(f"Processing fold #{i}")
    #准备验证数据
    val_data = train_data[i * num_val_samples: (i + 1) * num_val_samples]
    val_targets = train_targets[i * num_val_samples: (i + 1) * num_val_samples]
    #准备训练数据
    partial_train_data = np.concatenate(
        [train_data[:i * num_val_samples],
         train_data[(i + 1) * num_val_samples:]],
        axis=0)
    partial_train_targets = np.concatenate(
        [train_targets[:i * num_val_samples],
         train_targets[(i + 1) * num_val_samples:]],
        axis=0)
    #构建已编译的keras模型
    model = build_model()
    model.fit(partial_train_data, partial_train_targets,
              epochs=num_epochs, batch_size=16, verbose=0) #verbose=0,静默模式
    #在验证集上评估模型
    val_mse, val_mae = model.evaluate(val_data, val_targets, verbose=0)
    all_scores.append(val_mae)
#最终的分数
np.mean(all_scores)

总结

关于模型的验证:

  1. 可以在model.fit里内置验证集。
  2. 可以在model训练完后用model.evaluate(data,targets)来验证其他的验证集。

二分类问题:

  1. 对于二分类问题,网络的最后一层应该是只有一个单元并使用sigmoid激活的dense层,网络输出应该是0~1范围内的标量,表示概率值。
  2. 对于二分类问题的sigmoid标量输出,应该使用binary_crossentropy损失函数。
  3. 常用rmsprop优化器。

多分类问题:

  1. 最后一层的选择
    1. 如果要对n个类别进行分类,网络的最后一层应该是大小为n的dense层。
    2. 对于单标签,多分类问题。网络的最后一层应该使用softmax激活,这样可以输出多个输出类别上的概率分布。
  2. 损失函数的选择
    1. 对于多分类问题,最好的损失函数就是categorical_crossentropy(分类交叉熵)。可以衡量两个概率分布之间的距离,这里的两个概率分布分别是网络输出的概率分布和标签的真是分布。通过使两个分布距离达到最小化,使输出结果尽可能接近真是标签。
  3. 如果划分的类别较多,应避免使用太小的中间层。
  4. 处理多分类标签的两种方法
    1. 通过one-hot编码,使用categorical_crossentropy作为损失函数
    2. 将便签编码为整数,使用sparse_categorical_crossentropy作为损失函数

回归问题:

  1. 如果数据特征具有不同的取值范围,我们需要进行预处理,将每个特征单独缩放。
  2. 损失函数为MSW均方误差,是回归问题常用的损失函数。
  3. 如果要处理的数据很少,K折验证有助于可靠地评估模型。

你可能感兴趣的:(深度学习调包侠,深度学习)