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

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

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

一、从最简单的函数说起

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

xy
12.1
23.8
36.2
48.9
511.8

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

1. 函数的形式

我们假设这个函数的形式是:

def f(x, a, b, c):
    return a * x * x + b * x + 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 + c
            error = predicted - y
            da += error * x * x
            db += error * x
            dc += error
        
        # 更新参数
        a -= learning_rate * da
        b -= learning_rate * db
        c -= learning_rate * c
    
    return 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. 保存模型

import pickle

with open('model.pkl', 'wb') as f:
    pickle.dump(model, f)

2. 加载使用

with open('model.pkl', 'rb') as f:
    model = pickle.load(f)
    
result = model.predict(new_data)

总结:三种方法的对比

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

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

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


http://www.kler.cn/a/458875.html

相关文章:

  • java 上传txt json等类型文件解析后返回给前端
  • 虚拟机Centos下安装Mysql完整过程(图文详解)
  • 网络安全 | 物联网安全:从设备到网络的全方位防护
  • overscroll-behavior-解决H5在ios上过度滚动的默认行为
  • 自建私有云相册:Docker一键部署Immich,照片视频备份利器
  • GoldenDB组件及对应的用户和进程
  • 【机器学习】机器学习的基本分类-半监督学习-Ladder Networks
  • 【day20】集合深入探讨
  • Optional类:避免NullPointerException
  • Go语言的字符串处理
  • 每天40分玩转Django:Django Channels
  • react-native键盘遮盖底部输入框问题修复
  • 对于多个网站的爬虫管理和配置支持
  • 前端处理跨域的几种方式
  • AI 加持下的智能家居行业:变革、挑战与机遇
  • 深度学习-78-大模型量化之Quantization Aware Training量化感知训练QAT
  • LeetCode每日三题(五)双指针
  • 基于PLC的电梯控制系统(论文+源码)
  • 从Huggingface下载的数据集为arrow格式,如何从本地路径读取arrow数据并输出样例
  • Knowledge is power——Digital Electronics
  • pytorch基础之注解的使用--003
  • 「Mac玩转仓颉内测版55」应用篇2 - 使用函数实现更复杂的计算
  • 项目优化性能监控
  • 基于YOLOv10和BYTETracker的多目标追踪系统,实现地铁人流量计数功能(基于复杂场景和密集遮挡条件下)
  • 前端学习DAY29(1688侧边栏)
  • NPM组件包 vant部分版本内嵌挖矿代码