机器学习(3)-神经网络基础

139 阅读6分钟

神经网络及如何进行推理预测

Sequential模型

在TensorFlow的高级API Keras中,Sequential是一个用于构建神经网络模型的容器。

Sequential模型的详细步骤:

  • 步骤 1:导入库

首先导入TensorFlow及其Keras API

import tensorflow as tf
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Flatten, Conv2D
  • 步骤 2:定义模型结构

可以通过两种方式定义Sequential模型:在构造函数中传入一个层列表,或者使用add方法逐层添加

方式一:使用构造函数传入层列表

model = Sequential([
    Flatten(input_shape=(28, 28)),  # 输入层:展平层
    Dense(128, activation='relu'),  # 隐藏层:全连接层,ReLU激活函数
    Dense(10, activation='softmax') # 输出层:全连接层,Softmax激活函数
])

方式二:使用add方法逐层添加

model = Sequential()
model.add(Flatten(input_shape=(28, 28)))  # 输入层:展平层
model.add(Dense(128, activation='relu'))  # 隐藏层:全连接层,ReLU激活函数
model.add(Dense(10, activation='softmax')) # 输出层:全连接层,Softmax激活函数
  • 步骤 3:编译模型-model.compile()

在训练模型之前,需要对其进行编译,指定优化器、损失函数和评价指标:

model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])

步骤 4:训练模型-model.fit()

使用训练数据集对模型进行训练:

# 假设 x_train 和 y_train 是训练数据和标签
model.fit(x_train, y_train, epochs=10)

步骤 5:评估模型-model.evaluate()

使用测试数据集对模型进行评估:

# 假设 x_test 和 y_test 是测试数据和标签
test_loss, test_acc = model.evaluate(x_test, y_test)
print('Test accuracy:', test_acc)

步骤 6:进行预测-model.predict()

使用训练好的模型进行预测:

predictions = model.predict(x_test)
# predictions 是一个概率分布,选择最大概率的类别作为预测结果
predicted_labels = tf.argmax(predictions, axis=1)

前向传播实现(forword prop)

image.png

直接np.matmul()实现矩阵相乘(简化):

image.png

训练神经网络

损失函数BinaryCrossentropy和SpareseCategoricalCrossentropy

  • BinaryCrossentropy 是一种在深度学习中用于衡量二分类模型预测与真实标签之间误差的损失函数。它通常用于二分类任务

二分类交叉熵的公式如下:

Binary Crossentropy=1Ni=1N[yilog(y^i)+(1yi)log(1y^i)]\text{Binary Crossentropy} = -\frac{1}{N} \sum_{i=1}^{N} \left[ y_i \log(\hat{y}_i) + (1 - y_i) \log(1 - \hat{y}_i) \right] 在TensorFlow和Keras中,BinaryCrossentropy可以通过以下几种方式使用:

  1. 作为损失函数: 在模型编译过程中,指定loss参数为BinaryCrossentropy

    import tensorflow as tf
    from tensorflow.keras.models import Sequential
    from tensorflow.keras.layers import Dense
    
    # 创建一个简单的模型
    model = Sequential([
        Dense(10, activation='relu', input_shape=(8,)),
        Dense(1, activation='sigmoid')
    ])
    
    # 编译模型,使用 BinaryCrossentropy 作为损失函数
    model.compile(optimizer='adam', loss=tf.keras.losses.BinaryCrossentropy(), metrics=['accuracy'])
    # 或者
    # model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])
    
  2. 手动计算损失: 如果需要手动计算损失,可以直接调用tf.keras.losses.BinaryCrossentropy

    y_true = [[0], [1], [0], [1]]  # 真实标签
    y_pred = [[0.1], [0.9], [0.2], [0.8]]  # 模型预测
    
    bce = tf.keras.losses.BinaryCrossentropy()
    loss = bce(y_true, y_pred)
    
    print('Binary Crossentropy loss:', loss.numpy())
    
  • SparseCategoricalCrossentropy 是一种用于多类分类任务的损失函数。

公式: Sparse Categorical Crossentropy=1Ni=1Nlog(y^i,yi)\text{Sparse Categorical Crossentropy} = -\frac{1}{N} \sum_{i=1}^{N} \log(\hat{y}_{i,y_i})

其中,yiy_i是样本 𝑖 的真实类别索引(整数),y^i,yi\hat{y}_{i,y_i}是模型对于样本 𝑖 属于真实类别 yiy_i 的预测概率。

model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])

激活函数relu、sigmoid、softmax

  • ReLU(Rectified Linear Unit)

公式:ReLU(x)=max(0,x)\text{ReLU}(x) = \max(0, x)

特点:稀疏激活、计算简单、缓解梯度消失问题。

适用场景:

  1. 隐藏层:ReLU通常用于隐藏层,因为它可以加速训练并处理深层网络中的梯度问题。
  2. 深度学习模型:在卷积神经网络(CNN)和深层前馈神经网络(DNN)中广泛使用。

其他变种:如Leaky ReLU和Parametric ReLU,进一步改进ReLU的不足。

  • Sigmoid

公式:Sigmoid(x)=11+ex\text{Sigmoid}(x) = \frac{1}{1 + e^{-x}}

特点:输出范围(Sigmoid的输出范围在0到1之间,可以解释为概率)、梯度消失问题(在极端输入值情况下,梯度会非常小,导致梯度消失问题,影响深层网络的训练)、平滑输出(对于输出层需要概率解释的任务,Sigmoid是常用选择)

适用场景:

  1. 输出层:在二分类任务中,Sigmoid常用于输出层,将模型输出转化为概率。
  2. 简单网络:在浅层网络中有时使用,但在深层网络中通常不推荐使用。
  • Softmax

适用于多分类任务,它是Sigmoid在多分类情况下的推广。

多类分类与多标签分类

  • 多类分类 (Multi-class Classification):多类分类是指将每个样本分配到多个类别中的一个类别。每个样本只能属于一个类别,并且所有可能的类别是互斥的。
  • 多标签分类 (Multi-label Classification):多标签分类是指每个样本可以属于多个类别。类别之间不是互斥的,一个样本可以同时具有多个标签。

优化方法(梯度下降和Adam)

Adam:动态调整每个参数的学习率,适用于数据稀疏且高维、较复杂的神经网络。Adam通常比普通的梯度下降收敛速度更快,但需要更多的内存和计算资源。

# sgd梯度下降
model.compile(optimizer='sgd', loss='categorical_crossentropy', metrics=['accuracy'])
# adam
model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])

反向传播

从输出层向隐藏层求导计算损失,推导未细看,需要再按需学习。

实用建议和技巧

交叉验证确定多项式d次数

多项式次数d小,高偏差(bias);多项式次数d大,高方差(variance),即过拟合。

a8ee99972a86507ef1f1abc117efda9.png

交叉验证确定λ\lambda

λ\lambda大,高偏差(bias);λ\lambda小,高方差(variance),即过拟合。

82d61635177f0e0f2053573178eaa72.png

注意交叉验证关于多项式次数和λ\lambda的图像,类似镜像对称:

2eded3b57f8dc3cb3b02f8245c9c714.png

学习曲线

训练集增加,训练误差和交叉验证误差趋于稳定:

fde528552fe3e23f354e06109c0bc27.png

对于高偏差,即使投喂更多训练数据,误差也不会下降

对于高方差,交叉验证训练误差和交叉验证误差会有较大差距,但随着投喂数据的增加,训练误差和交叉验证误差会不断接近

不同情况对应解决措施:

a7db807a589358f6bd45f87629bd0c0.png

λ\lambda调整

Dense()函数中kernel_regularizer参数

误差分析、有效添加数据、迁移学习

误差分析:手动实现...

迁移学习:复制、微调...

精确率与召回率

精确率是指在所有被模型预测为正类(positive class,即被预测为1)的样本中,实际为正类的样本所占的比例。它反映了模型在预测正类时的准确性

Precision=TPTP+FP\text{Precision} = \frac{TP}{TP + FP}

召回率是指在所有实际为正类的样本中,被模型正确预测为正类的样本所占的比例。它反映了模型在识别正类样本方面的能力

Recall=TPTP+FN\text{Recall} = \frac{TP}{TP + FN}

其中:

  • TP是真阳性(True Positive)
  • FP是假阳性(False Positive)
  • FN是假阴性(False Negative)

引入公式来权衡精确率和召回率大小,比如f1公式:

F1=2×TPTP+FP×TPTP+FNTPTP+FP+TPTP+FN\text{F1} = 2 \times \frac{ \frac{TP}{TP + FP} \times \frac{TP}{TP + FN} }{ \frac{TP}{TP + FP} + \frac{TP}{TP + FN} } ,即F1=2PR/(P+R)

其他

  • sigmoid()函数,σ(x)=11+ex\sigma(x) = \frac{1}{1 + e^{-x}}
  • 矩阵转置:AT=A.T
  • 矩阵相乘:np.matmul(A,B)
  • np.array()创建数组
  • 张量(Tensor)是一种多维数据结构,是标量、向量和矩阵的泛化
  • a2.numpy() 将张量(tensor)转换为 NumPy 数组
  • 书 集体智慧编程
  • 黄海广博士的书 git上笔记?