目录
1.从函数分析到机器学习应用
1.1 3D曲面图可视化报告
1.1.1 目标
1.1.2 代码分析
1.1.3 结果分析
1.1.4 观察与总结
1.1.5 结论
1.2 一元函数梯度计算报告
1.2.1 目标
1.2.2 代码分析
1.2.4 计算结果
1.2.5 优势与意义
1.2.6 结论
1.3 一元函数梯度和二阶导数计算报告
1.3.1 目标
1.3.2 代码分析
1.3.3 计算结果
1.3.4 优势与意义
1.3.5 结论
1.4 多元函数梯度计算报告
1.4.1 目标
1.4.2 代码分析
1.4.3 梯度计算解析
1.4.4 优势与意义
1.4.5 结论
1.5 线性回归模型训练报告
1.5.1 目标
1.5.2 代码分析
1.5.3 结果分析
1.5.4 优势与意义
1.5.5 结论
2.基于BP神经网络的鸢尾花分类任务
2.1神经网络
2.1.1 BP神经
2.1.2 BP神经网络的工作流程
2.1.3 总结
2.1.4 任务目标
2.2 实验过程
2.2.1 数据加载与预处理
2.2.2 激活函数及其导数
2.2.3 BP神经网络实现
2.2.4 模型训练与测试
2.3 总结与改进建议
1.从函数分析到机器学习应用
1.1 3D曲面图可视化报告
1.1.1 目标
本次代码的目标是生成一个3D曲面图,用于展示数学函数 f(x,y)=−(x2+y2)的特性。通过在指定范围内绘制该函数,直观展示其三维空间中的变化情况。
1.1.2 代码分析
(1)函数定义:
def fun(x, y):
return -(np.power(x, 2) + np.power(y, 2))
函数 fun(x, y)
用于计算 −(x2+y2)的值,这是一种二次函数,其结果用于生成曲面图的Z轴值,构成抛物面。
(2)3D图表设置:
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
通过 plt.figure()
初始化图表,并添加了一个3D子图(projection='3d')用于绘制三维曲面。
(3)数据生成:
X0 = np.arange(-3, 3, 0.25)
X1 = np.arange(-3, 3, 0.25)
X0, X1 = np.meshgrid(X0, X1)
Z = fun(X0, X1)
使用 np.arange
生成从-3到3的范围,步长为0.25的数列。np.meshgrid
将生成的X0和X1网格化,形成二维坐标平面,随后通过 fun(X0, X1)
计算Z轴值。
(4)曲面绘制:
surf = ax.plot_surface(X0, X1, Z, cmap=plt.cm.winter)
使用 plot_surface
绘制曲面图,并通过 cmap=plt.cm.winter
设置了颜色映射,以便通过颜色反映Z值的大小。
(5)坐标轴标签:
ax.set_xlabel('X0', color='r')
ax.set_ylabel('X1', color='g')
ax.set_zlabel('f(x)', color='b')
设置了每个坐标轴的标签,并分别使用红色(X轴)、绿色(Y轴)和蓝色(Z轴)标注,增强了图表的可视化效果。
(6)颜色条:
fig.colorbar(surf)
添加了颜色条,帮助解释图表中颜色和Z值的对应关系。
(7)总体代码:
import numpy as np
import matplotlib.pyplot as plt
# 定义函数
def fun(x, y):
return -(np.power(x, 2) + np.power(y, 2))
# 创建 3D 图形对象
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d') # 添加3D子图
# 生成数据
X0 = np.arange(-3, 3, 0.25)
X1 = np.arange(-3, 3, 0.25)
X0, X1 = np.meshgrid(X0, X1)
Z = fun(X0, X1)
# 绘制曲面图,并使用 cmap 着色
surf = ax.plot_surface(X0, X1, Z, cmap=plt.cm.winter)
ax.set_xlabel('X0', color='r')
ax.set_ylabel('X1', color='g')
ax.set_zlabel('f(x)', color='b') # 给三个坐标轴注明坐标名称
# 添加颜色条
fig.colorbar(surf)
plt.show()
1.1.3 结果分析
生成的图表展示了函数 f(x,y)=−(x2+y2)的抛物面特性,呈现一个以原点为中心的对称碗状结构。颜色从蓝到绿,代表Z值从低到高的变化。右侧的颜色条清晰标注了每种颜色对应的具体值范围。
1.1.4 观察与总结
- 图表清晰地展示了函数的形态,其对称性和凹形特性一目了然。
- 使用颜色渐变提高了数据的直观表现能力,有助于快速理解函数的深度和高度变化。
- 坐标轴的颜色标注增强了可读性,使得三个维度的意义更加明确。
1.1.5 结论
该3D曲面图成功地将数学函数的空间特性可视化,为多变量函数的探索提供了直观的工具。类似的图表对于研究函数的分布特性、对称性或寻找极值点具有重要意义。
1.2 一元函数梯度计算报告
1.2.1 目标
本次代码的目标是通过TensorFlow框架,计算函数 f(x)=x2+2x−1 在指定点 x=2 处的一阶梯度(即导数)。
1.2.2 代码分析
(1)函数定义:
def func(x):
return x ** 2 + 2 * x - 1
定义了一元二次函数 f(x)=x2+2x−1。该函数的导数可通过自动微分工具计算,或手动计算为 f′(x)=2x+2。
(2)自动梯度计算:
with tf.GradientTape() as tape:
tape.watch(x)
y = func(x)
使用 TensorFlow 的 tf.GradientTape
实现自动梯度计算。tape.watch(x)
监测变量 x
的变化,确保其参与梯度计算。
(3)梯度提取:
order_1 = tape.gradient(target=y, sources=x)
调用 tape.gradient
方法,计算目标函数 y
对变量 x
的一阶梯度。
(4)输出结果:
print("函数 x ** 2 + 2 * x - 1 在 x = 2 处的梯度为: ", order_1.numpy())
将计算出的梯度转为NumPy数组,并在终端打印结果。
1.2.4 计算结果
根据代码执行,函数 f(x)=x2+2x−1 在 x=2 处的一阶导数为: f′(x)=2x+2代入 x=2,可得: f′(2)=2×2+2=6
程序输出与手动计算一致,验证了代码的正确性。
1.2.5 优势与意义
(1)代码优势:
- 利用 TensorFlow 自动微分机制,无需手动推导导数公式,适合复杂函数梯度计算。
- 可扩展至更高维度、多变量函数的梯度和偏导数计算。
(2)应用场景:
- 自动梯度计算在机器学习中十分重要,广泛应用于反向传播算法中优化模型参数。
- 数学建模或科学计算中,也可用于快速验证导数或梯度公式的正确性。
1.2.6 结论
本代码成功计算了一元二次函数在给定点的梯度,结果准确无误。TensorFlow 的自动梯度工具不仅提升了计算效率,也大幅减少了手动推导的可能错误。
1.3 一元函数梯度和二阶导数计算报告
1.3.1 目标
本次代码的目标是通过TensorFlow框架,计算函数 f(x)=x2+2x−1 在指定点 x=2 处的一阶梯度和二阶导数,验证自动微分机制的准确性。
1.3.2 代码分析
(1)变量定义:
x = tf.Variable(2.0, trainable=True)
定义变量 xxx,设置其值为 2.0,并声明其为可训练变量,以便被 GradientTape
监测并参与梯度计算。
(2)嵌套的梯度计算:
with tf.GradientTape() as tape1:
with tf.GradientTape() as tape2:
y = x ** 2 + 2 * x - 1
order_1 = tape2.gradient(y, x)
order_2 = tape1.gradient(order_1, x)
- 第一层
tape2
负责计算目标函数 f(x)f(x)f(x) 的一阶梯度。 - 第二层
tape1
监测一阶梯度的变化,计算其对 xxx 的导数,从而得到函数的二阶导数。
(3)结果输出:
print("在 x = 2 处的一阶梯度为: ", order_1.numpy())
print("在 x = 2 处的二阶梯度为: ", order_2.numpy())
将一阶梯度和二阶梯度的计算结果打印出来。
1.3.3 计算结果
根据程序输出:
- 一阶梯度(导数):f′(x)=2x+2,在 x=2 时,f′(2)=2×2+2=6。
- 二阶导数:f′′(x)=2,为常数。在 x=2 时,f′′(2)=2。
两项结果与手动计算完全一致,验证了代码的正确性。
1.3.4 优势与意义
代码优势:
- 利用
GradientTape
实现嵌套梯度计算,无需显式推导复杂函数的二阶导数,尤其适用于多变量函数的高阶导数计算。 - 灵活性高,可扩展至任意阶梯度计算。
应用场景:
- 高阶导数计算在物理建模(如加速度计算)和机器学习优化中(如Hessian矩阵计算)具有广泛应用。
- 自动微分降低了复杂计算的门槛,适合分析函数的曲率和极值点。
1.3.5 结论
本代码成功计算了一元二次函数在指定点的梯度和二阶导数,结果精确,充分体现了 TensorFlow 自动微分工具的强大功能。代码逻辑清晰,适合作为高阶导数计算的模板。
1.4 多元函数梯度计算报告
1.4.1 目标
本次代码的目标是利用 TensorFlow 框架,计算多元函数
在点 x=[1.0,2.0,3.0] 处的梯度。
1.4.2 代码分析
(1)函数定义:
def func(x):
return x[0] ** 2 + 3 * x[0] * x[1] + x[1] ** 2 + x[2] ** 3
定义了一个多元函数 f(x)f(x)f(x),其中 xxx 是一个三维张量。该函数包含二次项和三次项的组合。
(2)自动梯度计算:
x = tf.Variable([1.0, 2.0, 3.0], dtype=tf.float32)
with tf.GradientTape() as tape:
tape.watch(x)
y = func(x)
- 变量
x
被定义为可训练张量,初值为 [1.0,2.0,3.0]。 - 通过
GradientTape
监控张量x
,对其参与的运算生成梯度。
(3)梯度提取:
order_1 = tape.gradient(target=y, sources=x)
print("多元函数 x = [1.0, 2.0, 3.0] 的梯度为:", [grad.numpy() for grad in order_1])
- 使用
tape.gradient
方法计算目标函数 f(x) 对x
的一阶梯度。 - 因为
x
是一个张量列表,其梯度也是一个张量列表,逐项提取值后输出。
(4)输出结果: 程序输出:
多元函数 x = [1.0, 2.0, 3.0] 的梯度为: [8.0, 7.0, 27.0]
1.4.3 梯度计算解析
多元函数的梯度为:
在 x=[1.0,2.0,3.0]x = [1.0, 2.0, 3.0]x=[1.0,2.0,3.0] 处,逐项计算:
程序计算的结果与手动推导一致,验证了代码的正确性。
1.4.4 优势与意义
(1)代码优势:
- 自动计算多元函数的梯度,无需手动推导偏导数公式。
- 对任意维度和复杂度的函数,均能通过
GradientTape
快速计算梯度。
(2)应用场景:
- 梯度计算在机器学习中至关重要,用于优化目标函数。
- 多元函数梯度计算也适用于科学计算、最优控制和物理建模等领域。
1.4.5 结论
本代码准确计算了多元函数在指定点的梯度,结果精确,代码结构清晰,体现了 TensorFlow 自动微分的高效性和灵活性。代码适用于复杂多维问题的梯度计算,是学习和实践自动微分的优秀示例。
1.5 线性回归模型训练报告
1.5.1 目标
通过 TensorFlow 框架实现一个简单的线性回归模型,拟合目标函数 y=10x+5。最终验证模型对新输入数据的预测能力。
1.5.2 代码分析
(1)损失函数定义:
def loss(y_true, y_pred):
return tf.keras.losses.MeanSquaredError()(y_true, y_pred)
使用均方误差(MSE)作为损失函数,衡量预测值 ypred 和真实值 ytrue 的差距。
(2)训练数据生成:
x_train_inch = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11], dtype=np.float32)
y_train_price = np.array([10 * num + 5 for num in x_train_inch], dtype=np.float32)
模拟生成线性关系的数据:输入 x 为从 1 到 11 的整数,目标输出 y 通过公式 y=10x+5 计算。
(3)模型参数初始化:
w1 = tf.Variable(random.random(), trainable=True, dtype=tf.float32)
w0 = tf.Variable(random.random(), trainable=True, dtype=tf.float32)
初始化两个可训练参数 w1 和 w0 ,分别对应线性回归模型的斜率和截距。
(4)梯度下降更新函数:
def step_gradient(real_x, real_y, learning_rate):
with tf.GradientTape() as tape:
pred_y = w1 * real_x + w0
reg_loss = loss(real_y, pred_y)
w1_gradients, w0_gradients = tape.gradient(reg_loss, (w1, w0))
w1.assign_sub(w1_gradients * learning_rate)
w0.assign_sub(w0_gradients * learning_rate)
- 使用
GradientTape
计算损失函数对 w1 和 w0 的梯度。 - 更新规则:参数值减去学习率乘以梯度。
(5)训练循环:
learning_rate = 0.01
num_iterations = 1000
for _ in range(num_iterations):
step_gradient(tf.convert_to_tensor(x_train_inch), tf.convert_to_tensor(y_train_price), learning_rate)
通过 1000 次迭代,不断更新模型参数,最终使其拟合数据分布。
(6)模型评估:
wheat = 0.9
price = w1 * wheat + w0
print("price = {:.2f}".format(price.numpy()))
使用训练好的模型预测 x=0.9 对应的 y 值,并输出预测结果。
1.5.3 结果分析
拟合的模型: 程序输出:
拟合得到的模型近似为: y ≈ 10.005026817321777x + 4.961641311645508
说明模型基本收敛,参数 w1 和 w0 的值非常接近目标函数的真实值 w1=10、w0=5。
预测结果: 对于输入 x=0.9,程序输出:
price = 13.97
预测结果接近真实值 y=10×0.9+5=14,误差很小,说明模型拟合效果良好。
1.5.4 优势与意义
(1)代码优势:
- 使用 TensorFlow 的自动微分和变量更新功能,简化了梯度计算过程。
- 代码清晰明了,易于理解和扩展。
(2)应用场景:
- 线性回归模型是数据建模的基础,可扩展至多元线性回归、逻辑回归等。
- 适用于简单预测任务或作为复杂模型的初步验证工具。
1.5.5 结论
本代码成功实现了线性回归模型的训练,最终模型参数与真实目标函数参数非常接近,预测结果准确,证明了模型的拟合能力和代码的有效性。
2.基于BP神经网络的鸢尾花分类任务
2.1神经网络
2.1.1 BP神经
BP神经网络(Back Propagation Neural Network,反向传播神经网络)是一种前馈神经网络,通过误差反向传播算法来训练模型权重和偏置。它是人工神经网络中最常见的模型之一,特别适用于非线性函数的拟合和分类问题。
(1)BP神经网络的基本组成
- 输入层:负责接收输入数据,每个节点对应一个特征。
- 隐藏层:通过权重和激活函数进行非线性变换,可以有一层或多层。
- 输出层:生成预测结果,节点数由任务的输出维度决定(如分类问题中类别数,回归问题中输出值数)。
(2)BP神经网络的特点
- 基于误差反向传播算法,即将输出误差反向传播,调整网络参数(权重和偏置)。
- 可以处理多维输入和非线性问题。
- 通过梯度下降法或其变种来优化目标函数。
2.1.2 BP神经网络的工作流程
BP神经网络主要包括两个阶段:前向传播(Forward Propagation) 和 反向传播(Backward Propagation)。
(1)前向传播
- 输入数据通过输入层传递到隐藏层,再通过激活函数变换,最终传递到输出层。
- 计算输出值 ypred。
- 如果输出值与实际值(目标值)不符,计算误差(损失函数)。
计算公式:
- 假设权重矩阵为 W,偏置为 b,激活函数为 f(⋅),则:
- 其中 l表示第 l层,a(l−1)是上一层的输出。
(2)误差计算
- 定义损失函数 L,例如平方误差:
(3)反向传播
通过链式法则计算每个参数对损失函数的梯度,调整参数以减少误差。
步骤:
1.输出层误差:
其中 z(L)是输出层的输入,f′(z)是激活函数的导数。
2.隐藏层误差:
3.梯度更新: 使用梯度下降法调整权重和偏置:
其中 η是学习率。
(4)参数更新
- 通过多次迭代(Epoch)优化损失函数,直到达到期望的精度或停止条件。
2.1.3 总结
(1)BP神经网络的核心思想是:
- 前向传播:计算预测值。
- 误差计算:定义损失函数。
- 反向传播:计算梯度并更新参数。
- 迭代训练:通过多轮训练优化模型。
(2)优点:
- 能有效处理复杂的非线性问题。
- 在适当设置网络结构和参数时,具有很强的拟合能力。
(3)缺点:
- 容易陷入局部最优。
- 梯度消失问题影响深层网络训练。
为了改进其性能,可以结合改进优化算法(如Adam、RMSProp)或使用更深层的网络架构(如卷积神经网络、深度学习网络)。
2.1.4 任务目标
使用BP(反向传播)神经网络实现对鸢尾花数据集的分类,主要包括以下步骤:
- 数据加载与预处理。
- 自定义BP神经网络的实现,包括前向传播、反向传播和梯度更新。
- 训练模型并在测试集上评估分类性能。
2.2 实验过程
2.2.1 数据加载与预处理
(1)代码
# 1.加载和预处理数据
import numpy as np
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import OneHotEncoder, StandardScaler
# 加载鸢尾花数据集
iris = load_iris()
X, y = iris.data, iris.target
# 数据标准化和独热编码
# 标准化:将每个特征的值调整到均值为0,标准差为1
scaler = StandardScaler()
X = scaler.fit_transform(X)
# 独热编码:将类别标签转化为独热向量 (如 0 -> [1, 0, 0])
encoder = OneHotEncoder()
y = encoder.fit_transform(y.reshape(-1, 1)).toarray()
# 划分训练集和测试集
# 将80%的数据用于训练,20%用于测试
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
(2)分析
-
标准化处理:使用
StandardScaler
将特征数据的均值调整为0,标准差调整为1,提升训练的稳定性。 - 独热编码:将分类标签(0, 1, 2)转为独热向量形式,便于多分类任务的神经网络训练。
- 数据划分:将数据集按8:2比例划分为训练集和测试集。
2.2.2 激活函数及其导数
(1)代码
# 2.定义激活函数和导数
# Sigmoid 激活函数
def sigmoid(x):
"""
将输入值压缩到 (0, 1) 范围,用于激活神经元。
"""
return 1 / (1 + np.exp(-x))
# Sigmoid 激活函数的导数
def sigmoid_derivative(x):
"""
用于计算反向传播中的梯度。
对 Sigmoid 函数求导的结果是 f'(x) = f(x) * (1 - f(x))。
"""
return x * (1 - x)
(2)解析
- Sigmoid激活函数:将输入值映射到(0, 1)范围,用于神经元的激活操作。 f(x)=11+e−x
- Sigmoid函数的导数:用于反向传播中梯度计算: f′(x)=f(x)⋅(1−f(x))
2.2.3 BP神经网络实现
(1)代码
# 3.定义 BP 神经网络类
class BPNeuralNetwork:
def __init__(self, input_size, hidden_size, output_size, learning_rate=0.01):
"""
初始化神经网络参数,包括权重、偏置和学习率。
参数:
- input_size: 输入层节点数
- hidden_size: 隐藏层节点数
- output_size: 输出层节点数
- learning_rate: 学习率,控制梯度更新步长
"""
# 输入层到隐藏层的权重矩阵,初始化为随机值
self.weights_input_hidden = np.random.uniform(-1, 1, (input_size, hidden_size))
# 隐藏层的偏置
self.bias_hidden = np.zeros((1, hidden_size))
# 隐藏层到输出层的权重矩阵,初始化为随机值
self.weights_hidden_output = np.random.uniform(-1, 1, (hidden_size, output_size))
# 输出层的偏置
self.bias_output = np.zeros((1, output_size))
# 学习率
self.learning_rate = learning_rate
def forward(self, X):
"""
执行前向传播,计算隐藏层和输出层的激活值。
参数:
- X: 输入数据
返回:
- final_output: 网络的最终输出
"""
# 计算隐藏层的加权输入 (Z = X * W + b)
self.hidden_input = np.dot(X, self.weights_input_hidden) + self.bias_hidden
# 隐藏层的激活输出 (A = Sigmoid(Z))
self.hidden_output = sigmoid(self.hidden_input)
# 计算输出层的加权输入 (Z = H * W + b)
self.final_input = np.dot(self.hidden_output, self.weights_hidden_output) + self.bias_output
# 输出层的激活输出 (A = Sigmoid(Z))
self.final_output = sigmoid(self.final_input)
return self.final_output
def backward(self, X, y, output):
"""
执行反向传播,计算误差并更新权重和偏置。
参数:
- X: 输入数据
- y: 实际标签
- output: 模型输出
"""
# 输出层误差 (Error = y - output)
output_error = y - output
# 输出层梯度 (Delta = Error * f'(output))
output_delta = output_error * sigmoid_derivative(output)
# 隐藏层误差 (传播到隐藏层的误差)
hidden_error = np.dot(output_delta, self.weights_hidden_output.T)
# 隐藏层梯度 (Delta = Error * f'(hidden_output))
hidden_delta = hidden_error * sigmoid_derivative(self.hidden_output)
# 更新隐藏层到输出层的权重和偏置
self.weights_hidden_output += self.learning_rate * np.dot(self.hidden_output.T, output_delta)
self.bias_output += self.learning_rate * np.sum(output_delta, axis=0, keepdims=True)
# 更新输入层到隐藏层的权重和偏置
self.weights_input_hidden += self.learning_rate * np.dot(X.T, hidden_delta)
self.bias_hidden += self.learning_rate * np.sum(hidden_delta, axis=0, keepdims=True)
def train(self, X, y, epochs):
"""
训练神经网络。
参数:
- X: 训练数据
- y: 训练标签
- epochs: 训练的迭代次数
"""
for epoch in range(epochs):
# 前向传播
output = self.forward(X)
# 反向传播
self.backward(X, y, output)
# 每隔100个 epoch 打印一次损失值
if epoch % 100 == 0:
loss = np.mean(np.square(y - output)) # 均方误差
print(f"Epoch {epoch}, Loss: {loss}")
def predict(self, X):
"""
使用训练好的网络进行预测。
参数:
- X: 测试数据
返回:
- 预测类别(最大概率对应的索引)
"""
output = self.forward(X)
return np.argmax(output, axis=1) # 返回概率最大的类别索引
(2)详细解析
1. 初始化网络参数
- 输入层到隐藏层、隐藏层到输出层的权重和偏置分别初始化。
- 使用随机值初始化权重,偏置初始化为0,学习率控制参数更新步长。
2. 前向传播
- 隐藏层计算:
- 输出层计算:
3. 反向传播
- 输出层误差:
- 隐藏层误差:
4. 权重更新
2.2.4 模型训练与测试
(1)代码
# 4.训练和评估模型
# 4.1 初始化神经网络
input_size = X_train.shape[1] # 输入层节点数:特征数量
hidden_size = 2 # 隐藏层节点数:可以调节
output_size = y_train.shape[1] # 输出层节点数:类别数量
learning_rate = 0.1 # 学习率
# 创建网络实例
bp_nn = BPNeuralNetwork(input_size, hidden_size, output_size, learning_rate)
# 训练神经网络
bp_nn.train(X_train, y_train, epochs=1000)
# 使用测试集进行预测
predictions = bp_nn.predict(X_test)
# 计算准确率
accuracy = np.mean(predictions == np.argmax(y_test, axis=1))
print(f"Test Accuracy: {accuracy * 100:.2f}%")
(2)实验结果
1.训练过程:
Epoch 0, Loss: 0.22128556516365086 Epoch 100, Loss: 0.021410587809142765 Epoch 200, Loss: 0.013800814452345782 Epoch 300, Loss: 0.012100929959213873 Epoch 400, Loss: 0.011392964488187917 Epoch 500, Loss: 0.011017511806778143 Epoch 600, Loss: 0.010790199253609335 Epoch 700, Loss: 0.010640489751476679 Epoch 800, Loss: 0.010535921139959336 Epoch 900, Loss: 0.01045957534860003
测试集准确率:
Test Accuracy: 100.00%
2.3 总结与改进建议
(1)模型表现:
- BP神经网络成功实现对鸢尾花数据的分类,测试集准确率达到100%。
(2)改进建议:
- 非线性激活函数:可尝试ReLU等激活函数,加速训练。
- 优化算法:引入Adam等优化算法提升收敛速度。
- 正则化:通过Dropout或L2正则防止过拟合。