TensorFlow DAY2: 搭建神经网络(PART 2)

TensorFlow 作为深度学习框架,当然是为了帮助我们更便捷地去构建神经网络。所以,本文将会了解如何使用 TensorFlow 来构建神经网络,并学会 TensorFlow 构建神经网络的重要函数和方法。

知识点
  • NumPy 构建神经网络
  • TensorFlow 构建神经网络
  • TensorFlow 完成 DIGITS 分类
  • TensorFlow 实现 Mini Batch 训练

NumPy 构建神经网络

前文中,我们已经了解了 TensorFlow 的工作机制,并学会使用 TensorFlow 参与运算。TensorFlow 作为最出色的深度学习开源框架,在我看来主要有 2 点优势。第一是基于计算图的数值计算过程,最终目的是提升计算速度。其次就是对各种常用神经网络层进行封装,提高构建模型的速度。

所以,本次实验我们将了解如何使用 TensorFlow 构建神经网络。

人工神经网络的实验中,我们使用 NumPy 构建简单的全连接神经网络。全连接指的是其每一个节点都与上一层每个节点相连。例如我们当时实现过的网络结构:

对于神经网络的实现,主要是前向传播和反向传播两个部分。前向传播当然是从输入 → 输出的计算,而反向传播则通过计算梯度来更新网络权重。这里,我们直接将前面感知机和人工神经网络实验中写过的代码拿过来使用。

复制代码
import numpy as np

class NeuralNetwork:
    def __init__(self, X, y, lr):
        """初始化参数"""
        self.input_layer = X
        self.W1 = np.ones((self.input_layer.shape[1], 3))  # 初始化权重全为 1
        self.W2 = np.ones((3, 1))
        self.y = y
        self.lr = lr

    def forward(self):
        """前向传播"""
        self.hidden_layer = sigmoid(np.dot(self.input_layer, self.W1))
        self.output_layer = sigmoid(np.dot(self.hidden_layer, self.W2))
        return self.output_layer

    def backward(self):
        """反向传播"""
        d_W2 = np.dot(self.hidden_layer.T, (2 * (self.output_layer - self.y) *
                                            sigmoid_derivative(np.dot(self.hidden_layer, self.W2))))

        d_W1 = np.dot(self.input_layer.T, (
            np.dot(2 * (self.output_layer - self.y) * sigmoid_derivative(
                   np.dot(self.hidden_layer, self.W2)), self.W2.T) * sigmoid_derivative(
                np.dot(self.input_layer, self.W1))))

        # 参数更新
        self.W1 -= self.lr * d_W1
        self.W2 -= self.lr * d_W2

下面,使用示例数据完成神经网络训练。

复制代码
import pandas as pd

# 直接运行加载数据集
df = pd.read_csv(
    "https://labfile.oss.aliyuncs.com/courses/1081/course-12-data.csv", header=0)
df.head()  # 预览前 5 行数据

from matplotlib import pyplot as plt
%matplotlib inline

X = df[['X0', 'X1']].values  # 输入值
y = df[['Y']].values  # 真实 y
nn_model = NeuralNetwork(X, y, lr=0.001)  # 定义模型
loss_list = []  # 存放损失数值变化

def sigmoid(x):
    """激活函数"""
    return 1 / (1 + np.exp(-x))

def sigmoid_derivative(x):
    """sigmoid 函数求导"""
    return sigmoid(x) * (1 - sigmoid(x))

# 迭代 200 次
for _ in range(200):
    y_ = nn_model.forward()  # 前向传播
    nn_model.backward()  # 反向传播
    loss = np.square(np.subtract(y, y_)).mean()  # 计算 MSE 损失
    loss_list.append(loss)

plt.plot(loss_list)  # 绘制 loss 曲线变化图
plt.title(f"final loss: {loss}")

可以看到,仅包含 1 个隐含层的网络,使用 NumPy 实现的代码量就已不算少。深度神经网络中,可能会有数百层及数千个神经元,使用 NumPy 实现的复杂度可想而知。

如果你仔细观察上面的代码,你就会发现随着神经网络的复杂程度增加,不仅代码量不断加大,最大的麻烦还在于求解梯度。所以,像 TensorFlow 等深度学习框架带来的最大便利在于,我们仅需要构建一个神经网络前向传播图,训练时就能够实现自动求导并更新参数。下面,我们就尝试使用 TensorFlow 的方式来重新构建上方包含 1 个隐含层的神经网络,并最终完成训练。

复制代码
import tensorflow as tf

# 将数组转换为常量张量
X = tf.cast(tf.constant(df[['X0', 'X1']].values), tf.float32)
y = tf.constant(df[['Y']].values)

X.shape, y.shape

上面的代码中,tf.cast 主要用于转换张量,类型为 tf.float32,这是为了和后面权重张量类型统一。通过输出可以看出,样本为 150 个,特征为 2 个,目标值 1 个。

定义模型类

接下来,我们就可以构建前向传播计算图了。这部分与 NumPy 构建前向传播过程非常相似,只是更换为使用 TensorFlow 构建。一般情况下,我们会将前向传播过程使用自定义模型类封装,并使用 TensorFlow 提供的 tf.Variable 随机初始化参数 W。

复制代码
class Model(object):
    def __init__(self):
        # 初始化权重全为 1,也可以随机初始化
        # 选择变量张量,因为权重后续会不断迭代更新
        self.W1 = tf.Variable(tf.ones([2, 3]))
        self.W2 = tf.Variable(tf.ones([3, 1]))

    def __call__(self, x):
        hidden_layer = tf.nn.sigmoid(tf.linalg.matmul(X, self.W1))  # 隐含层前向传播
        y_ = tf.nn.sigmoid(tf.linalg.matmul(hidden_layer, self.W2))  # 输出层前向传播
        return y_
相关推荐
奔跑中的小象6 小时前
统信UOS + 天数AI卡部署SGLang服务手册
人工智能·uos·sglang·天数智芯
DevSecOps选型指南6 小时前
中国版Mythos,为何是悬镜安全灵脉CodeAI?
人工智能·安全
Shockang6 小时前
LangGraph 状态机实战
人工智能
刹那芳华19926 小时前
循环神经网络的从零开始实现(RNN)
人工智能·rnn·深度学习
阿童木写作7 小时前
跨境图片翻译工具多合一,批量图片视频字幕翻译加智能抠图
人工智能·python·音视频·语音识别
科技之门7 小时前
AI3D从建模到贴图、绑骨和动画的完整流程怎么做?V2Fun完整工作流指南
人工智能·3d·贴图
宇宙第一小趴菜7 小时前
二、机器学习的应用领域和发展史
人工智能·机器学习
前端开发江鸟7 小时前
我写过 MCP Server,却一直以为 MCP 只有 Tool
人工智能
天国梦7 小时前
自习室智能化升级避坑指南:天学网AI智习室方案实测与选型建议
大数据·人工智能
阿里云云原生8 小时前
可用性从 99.9% 跃升至 99.995%:畅捷通如何用 AI 重塑运维底座?
运维·网络·人工智能