当前位置: 首页 > news >正文

(二)当人工智能是一个函数时,怎么去训练它?

还记得上次我们讲到,人工智能本质上就是一个函数。那么今天,让我们更进一步:这个函数是怎么练成的?

一、从最简单的函数说起

假设我们有这样一组数据:

xy
12.1
23.8
36.2
48.9
511.8

看着这组数据,你是否觉得它们之间存在某种关系?没错,它们大致符合一个二次函数的形态!

1. 函数的形式

我们假设这个函数的形式是:
f ( x ) = a x 2 + b x + c f(x) = a x^2 + b x + c f(x)=ax2+bx+c

这里:

  • x 是输入变量
  • a, b, c 是函数的参数
  • f(x) 是输出结果

2. 如何确定参数?

方法一:直接求解法

如果我们选择其中三个点,可以列出三个方程:

a(1)² + b(1) + c = 2.1
a(2)² + b(2) + c = 3.8
a(3)² + b(3) + c = 6.2

解这个方程组就能得到 a, b, c 的值。但这种方法有局限性:

  • 只能用有限的点
  • 方程组可能无解
  • 不能处理有噪声的数据
方法二:最小二乘法

同样,因为我们希望拟合的函数形式为:
f ( x ) = a x 2 + b x + c f(x) = a x^2 + b x + c f(x)=ax2+bx+c

其中:

  • x x x 是输入变量。
  • y i y_i yi 是已知的真实输出值。
  • a a a b b b c c c 是需要计算的参数。

我们用预测值 y ^ i = a x i 2 + b x i + c \hat{y}_i = a x_i^2 + b x_i + c y^i=axi2+bxi+c 表示模型生成的输出。目标是最小化预测值与真实值的误差平方和,即损失函数:
J ( a , b , c ) = ∑ i = 1 n ( y i − y ^ i ) 2 = ∑ i = 1 n ( y i − ( a x i 2 + b x i + c ) ) 2 J(a, b, c) = \sum_{i=1}^n (y_i - \hat{y}_i)^2 = \sum_{i=1}^n (y_i - (a x_i^2 + b x_i + c))^2 J(a,b,c)=i=1n(yiy^i)2=i=1n(yi(axi2+bxi+c))2

为了让上式的误差最小化,我们需要对 a a a b b b c c c 求偏导数,并让导数为零。这时,可以得到一组关于 a a a b b b c c c 的线性方程组。以矩阵形式表示为:
请添加图片描述

求解这个方程组即可得到参数 a a a b b b c c c

以下是基于 Python 的最小二乘法计算二次函数参数的代码实现:

import numpy as np# 输入数据:x 和 y
x = np.array([1, 2, 3, 4, 5])  # 自变量
y = np.array([2.1, 3.8, 6.2, 8.9, 11.8])  # 因变量# 构造矩阵
X = np.vstack([x**2, x, np.ones(len(x))]).T  # 包括 x^2、x 和常数项1
Y = y.reshape(-1, 1)  # 转换为列向量# 最小二乘法计算: (X^T * X)^(-1) * (X^T * Y)
theta = np.linalg.inv(X.T.dot(X)).dot(X.T).dot(Y)  # 求解线性方程
a, b, c = theta.flatten()  # 提取参数print(f"拟合结果:a = {a:.3f}, b = {b:.3f}, c = {c:.3f}")
方法三:梯度下降

这是机器学习中最常用的方法。其核心思想是:

  1. 随机初始化参数
  2. 计算损失函数对各参数的梯度
  3. 沿着梯度的反方向更新参数
  4. 重复步骤2-3直到收敛
def gradient_descent(x_data, y_data, learning_rate=0.0001, epochs=1000):a, b, c = 0, 0, 0  # 初始化参数for epoch in range(epochs):da, db, dc = 0, 0, 0  # 梯度初始化# 计算梯度for x, y in zip(x_data, y_data):predicted = a * x * x + b * x + cerror = predicted - yda += error * x * xdb += error * xdc += error# 更新参数a -= learning_rate * dab -= learning_rate * dbc -= learning_rate * creturn a, b, c

梯度下降算法

二、推广到神经网络

实际的神经网络比这个复杂得多,但基本思想是一样的:

简易神经网络图

1. 更复杂的函数形式

def neural_network(x, weights, biases):layer1 = sigmoid(np.dot(x, weights[0]) + biases[0])layer2 = sigmoid(np.dot(layer1, weights[1]) + biases[1])return layer2

2. 更多的参数

  • 不再是简单的a, b, c
  • 可能有成千上万个参数
  • 参数之间有复杂的关联关系

3. 更复杂的训练过程

  • 需要大量的训练数据
  • 使用反向传播算法计算梯度
  • 采用各种优化算法(如Adam)来更新参数

三、如何判断训练成功?

1. 验证集评估

把数据分成训练集和验证集,用验证集检验模型性能。

2. 常用评估指标

  • 回归问题:MSE(均方误差)、MAE(平均绝对误差)
  • 分类问题:准确率、召回率、F1分数

3. 过拟合问题

训练过程对比
注意这张图片仅仅是一个示意图,最左边的图片表示欠拟合,也就是函数训练不到位;中间的图片表示训练得比较好,最右边的图为过拟合,也就是说这种情况训练得到的函数过于逼近原始数据,倒是其泛化性能不够好。注意这里提到的泛化性能是一个人工智能领域经常会遇到的概念,后面的文章再展开讨论。

四、训练好的函数如何使用?

1. 基于训练好的参数构建完整的函数

就像第一部分假设的,我们有如下数据集:

xy
12.1
23.8
36.2
48.9
511.8

如下函数:
f ( x ) = a ∗ x 2 + b ∗ x + c f(x) = a * x² + b * x + c f(x)=ax2+bx+c

假如我们通过前面介绍的方法(直接求解、最小二乘或者梯度下降)训练得到了参数如下:

  • a = 0.38
  • b = 1.65
  • c = 0.07

这里的 abc 通常也被称为模型的参数
此时,完整的函数就变成:
f ( x ) = 0.38 ∗ x 2 + 1.65 ∗ x + 0.07 f(x) = 0.38 * x² + 1.65 * x + 0.07 f(x)=0.38x2+1.65x+0.07

2. 使用训练好的函数(模型推理)

模型推理的过程,其实就是将输入值代入训练好的函数,输出结果。这是它发挥作用的关键步骤。我们可以用训练好的函数预测新的输入数据下的结果。

  • 输入 x = 6,得:
    f(6) = 0.38 * 6² + 1.65 * 6 + 0.07 = 15.53
  • 输入 x = 7,得:
    f(7) = 0.38 * 7² + 1.65 * 7 + 0.07 = 19.74

可以通过下面的图更直观看到训练的效果:
请添加图片描述

总结:三种方法的对比

方法优点缺点适用场景
直接求解精确,计算快只适用于简单问题方程组规模小,无噪声
最小二乘有闭式解,计算稳定计算复杂度高回归问题,曲线拟合
梯度下降通用性强,可处理大规模问题可能陷入局部最优深度学习,复杂非线性问题

理解了这些基础,你就会发现:人工智能不过是一个不断调整参数、优化结果的过程。它的神奇之处不在于多么复杂,而在于如何把复杂的问题简化成可解的数学模型。

下次我们将继续探讨更多人工智能的有趣话题,记得点赞关注!


http://www.mrgr.cn/news/81994.html

相关文章:

  • Unity Canvas中显示粒子特效
  • 什么是自治系统和非自治系统
  • pdf预览兼容问题- chrome浏览器105及一下预览不了
  • 改进爬山算法之四:概率爬山法(Probabilistic Hill Climbing,PHC)
  • 开源存储详解-分布式存储与ceph
  • 前端-动画库Lottie 3分钟学会使用
  • CGAL windows 安装教程
  • 大厂高频总线协议面试题及参考答案(几百家面试题挑选最高频精华)
  • 斗鱼Android面试题及参考答案
  • MOS管驱动方案汇总
  • Unity设置中文
  • PHP框架+gatewayworker实现在线1对1聊天--gatewayworker说明(2)
  • 使用 commitlint 和 husky 检查提交描述是否符合规范要求
  • STM32 软件I2C读写
  • Prometheus 专栏 —— Prometheus安装、配置
  • 仙盟系统开发——启动app失败
  • Leecode刷题C语言之二叉树中的链表
  • o1到o3的发展历程
  • 【2024年-7月-20日-开源社区openEuler实践记录】openEuler - Docker - Images:容器化世界的得力助手
  • 【Qt】容器控件、布局管理控件
  • 24.小R的随机播放顺序<字节青训营-中等题>
  • PySide6 一些基础资料
  • 选择器(结构伪类选择器,伪元素选择器),PxCook软件,盒子模型
  • Flutter封装一个三方ViewPager学习
  • 如何规范的提交Git?
  • 「Mac畅玩鸿蒙与硬件48」UI互动应用篇25 - 简易购物车功能实现