摘要
Abstract
一、李宏毅机器学习系列课程-机器学习基础
1.1 机器学习任务
1.2 机器学习步骤
1.3 Linear Model
二、pytorch入门
2.1 张量Tensors
2.2 声明和定义
2.3 操作
2.4 与 Numpy 数组的转换
  2.4.1 Tensor 转换为 Numpy 数组
  2.4.2 Numpy 数组转换为 Tensor
2.5 CUDA张量
总结

摘要

本周系统学习了李宏毅机器学习基础内容,深入理解了机器学习的三大核心任务,即回归任务、分类任务和结构化学习,以及完整的训练流程,包括模型定义、损失函数设计和基于梯度下降的优化方法。同时,掌握了 PyTorch 的核心操作,例如张量的创建与运算如加法、索引和尺寸修改,张量与 NumPy 数组的相互转换,以及如何利用 GPU 加速计算的 CUDA 张量应用。

Abstract

This week focused on systematically studying the foundational concepts from Li Hongyi’s machine learning course. It involved gaining a deep understanding of the three core machine learning tasks: regression, classification, and structured learning, along with the complete training workflow encompassing model definition, loss function design, and optimization via gradient descent. Concurrently, core PyTorch operations were mastered, including tensor creation and manipulation such as addition, indexing, and reshaping, the bidirectional conversion between tensors and NumPy arrays, and the application of CUDA tensors to leverage GPU acceleration for computation.

一、李宏毅机器学习系列课程-机器学习基础

1.1机器学习任务

机器学习任务可以分为三个:Regression、Classification、Structured Learning
Regression:The function outputs a scalar.
在这里插入图片描述
Classification:Given options(classes),the function outputs the current one.
区分是否为垃圾邮件
Structured Learning:create something with structure(image、document).

1.2机器学习步骤

Function with unknown parameters(写出一个带有未知参数的函数)

举例
机器学习找这个函式的过程,分成三个步骤,那我们就用Youtube频道,点阅人数预测这件事情,来跟大家说明这三个步骤,是怎么运作的。

Step 1. Function with Unknown Parameters
在这里插入图片描述
第一个步骤是我们要写出一个带有未知参数的函式。可以先做一个最初步的猜测,比如写成这个样子:y=b+w*xₗ。每一个数值含义如下:

  • y是我们准备要预测的东西,我们准备要预测的是今天(2月26号)这个频道总共观看的人,叫做模型(Model);
  • xₗ是这个频道前一天总共观看的人数,y跟xₗ都是数值,叫做特征(Feature);
  • b(Bias)跟w(weight)是未知的参数(Parameter),它是准备要通过资料去找出来的,我们还不知道w跟b应该是多少,我们只是隐约的猜测;

Step 2. Define Loss from Training Data
定义Loss Function,即L(b,w)。这个Function的输入是Parameter,即模型(Model)里面的参数b和w。输出的值代表这笔数值好还是不好。
Loss计算方法:函式预估的结果跟真正的结果(这个真实的值叫做Label)的差距有多大。估测的值用y来表示,真实的值用ŷ来表示,计算y跟ŷ之间的差距eₗ。
在这里插入图片描述
计算差距不止一种方式

  • 算y跟ŷ之间,绝对值的差距,这一种计算差距的方法,得到的这个大L,得到的Loss叫 mean absolute error(MAE)
  • 如果e是用相减y的平方算出来的,这个叫mean square error(MSE)
  • 如果y和ŷ它都是机率分布的话,可能会选择Cross-entropy

接下来我们把每一天的误差加起来然后取得平均,N代表训验资料的个数,算出一个L,是每一笔训练资料的误差,就是Loss。L越大,代表现在这一组参数越不好,L越小,代表现在这一组参数越好。
对所计算出来的结果,那我们可以调整不同的w和b,组合起来以后,去计算它的Loss,然后就可以画出下面的这个等高线图。
在这里插入图片描述
如上图所示,越偏红色系,代表计算出来的Loss越大,就代表这一组w跟b越差,如果越偏蓝色系,就代表Loss越小,就代表这一组w跟b越好。那像这样子的一个等高线图,就是试着试了不同的参数,然后计算它的Loss,画出来的这个等高线图,叫做Error Surface,那这个是机器学习的第二步。

Step 3. Optimization
解一个最佳化的问题:把未知的参数w跟b,找一个数值出来,代入L,让Loss的值最小,那个就是我们要找的w跟b。
在这一门课里面唯一会用到的Optimization方法,叫做梯度下降法(Gradient Descent)。先假设未知的参数只有w。
那当w代不同的数值的时候,就会得到不同的Loss,这一条曲线就是error surface。那怎么样找一个w,去让这个loss的值最小呢?
在这里插入图片描述
首先随机选取一个初始的点w₀。接下来进行计算,在w等于w0的时候,w这个参数对loss的微分L/∂w |(w=w^0 ),计算在w₀这个位置的error surface的切线斜率。如果斜率为负值,说明左高右低,提高w值可以降低loss;如果斜率为正值,可以降低w。
这一步的步伐的大小取决于两件事情

  • 第一件事情是这个地方的斜率有多大,这个地方的斜率大,这个步伐就跨大一点,斜率小步伐就跨小一点。
  • 另外一个东西会影响步伐大小,叫做η学习速率(learning rate),它是你自己设定的。如果η设大一点,那你每次参数update就会量大。这种你在做机器学习需要自己设定的东西叫做hyperparameters。
    在这里插入图片描述

把w⁰往右移一步,那这个新的位置就叫做w¹,然后再继续反覆做同样的操作,不断的把w移动位置,最后你会停下来。
停下来往往有两种状况:

  • 第一种状况开始的设定,最多计算几次。
  • 那还有另外一种理想上的,微分的值正好是0的时候,如果这一项正好算出来是0,0乘上learning rate η还是0。

Gradient Descent 这个方法,大部分认为有一个巨大的问题,在这个例子里面,从W0当作随机初始的位置,很有可能走到WT这里,你的训练就停住了,你就没有办法再移动w的位置。那右侧红点这一个位置,这个真的可以让loss最小的地方,叫做全局最小值(global minima),而W^T这个地方叫做局部最小值(local minima)。李宏毅老师提出这个local minima是个假命题,真正的缺点并不是这个。
在这里插入图片描述
在有两个参数的情况下,用Gradient Descent:现在有两个参数,都给它随机的初始的值,就是w⁰跟b⁰。要计算w跟loss的微分和b对loss的微分,计算是在w等于w⁰的位置,b等于b₀的位置,计算w对L的微分,计算b对L的微分。计算完以后,就根据之前一个参数的时候的做法去更新w跟b,把w⁰减掉learning rate乘上微分的结果得到w¹,把b⁰减掉learning rate乘上微分的结果得到b¹。
在这里插入图片描述

1.3 Linear Model

三个步骤合起来叫做训练。我们现在是在知道答案的资料上去计算loss。但是我们真正要在意的是未来的观看的次数是多少,所以接下来拿这个函式来真的预测一下未来的观看次数。
在这里插入图片描述
在做得更好之前,我们先来分析一下结果:
在这里插入图片描述

  • 横轴是代表的是时间,所以0(最左边的点),代表的是2021年1月1号,最右边点代表的是2021年2月14号;
  • 纵轴就是观看的人次,这边是用千人当作单位;
  • 红色的线是真实的观看人次
  • 蓝色的线是机器用这一个函式,预测出来的观看人次

这蓝色的线没什么神奇的地方,因为我们觉得,可以拿前一天的观看人次去预测隔天的观看人次。但是仔细观察这个图,它是有周期性的,它每隔七天就会有两天特别低,所以既然我们已经知道每隔七天是一个循环,那这一个model显然很烂,因为它只能够看前一天。
每隔七天它一个循环,如果我们一个模型,它是参考前七天的资料,把七天前的资料,直接复制到拿来当作预测的结果,也许预测的会更准也说不定,所以我们就要修改一下我们的模型。通常一个模型的修改,往往来自于你对这个问题的理解,就是Domain Knowledge。
所以一开始,我们对问题完全不理解的时候,我们就胡乱写一个 y=b+wx_1 ,效果并没有特别好。接下来我们观察了真实的数据以后,得到一个结论是,每隔七天有一个循环,所以我们应该要把,前七天的观看人次都列入考虑,所以写了一个新的模型。

二、Pytorch入门

Pytorch 是一个基于 Python 的科学计算库,它面向以下两种人群:
希望将其代替 Numpy 来利用 GPUs 的威力;
一个可以提供更加灵活和快速的深度学习研究平台。

2.1 张量Tensors

Pytorch 的一大作用就是可以代替 Numpy 库,所以首先介绍 Tensors ,也就是张量,它相当于 Numpy 的多维数组(ndarrays)。两者的区别就是 Tensors 可以应用到 GPU 上加快计算速度。
首先导入必须的库。

import torch

2.2 声明和定义

首先是对 Tensors 的声明和定义方法,分别有以下几种:

  1. torch.empty(): 声明一个未初始化的矩阵。
# 创建一个 5*3 的矩阵
x = torch.empty(5, 3)
print(x)
  1. torch.rand():随机初始化一个矩阵
# 创建一个随机初始化的 5*3 矩阵
rand_x = torch.rand(5, 3)
print(rand_x)
  1. torch.zeros():创建数值皆为 0 的矩阵
# 创建一个数值皆是 0,类型为 long 的矩阵
zero_x = torch.zeros(5, 3, dtype=torch.long)
print(zero_x)

类似的也可以创建数值都是 1 的矩阵,调用 torch.ones

  1. torch.tensor():直接传递 tensor 数值来创建
# tensor 数值是 [5.5, 3]
tensor1 = torch.tensor([5.5, 3])
print(tensor1)
#tensor0 = torch.tensor([[1,2],[3,4],[5,6]])
#print(tensor0)

除了上述几种方法,还可以根据已有的 tensor 变量创建新的 tensor 变量,这种做法的好处就是可以保留已有 tensor 的一些属性,包括尺寸大小、数值属性,除非是重新定义这些属性。

2.3 操作

操作也包含了很多语法,这里仅以加法操作作为例子进行介绍,更多的操作介绍可以点击网址查看官方文档,包括转置、索引、切片、数学计算、线性代数、随机数等。

对于加法的操作,有几种实现方式:

  1. 加号(+) 运算符
  2. torch.add(tensor1, tensor2, [out=tensor3]),以新的张量tensor3输出
  3. tensor1.add_(tensor2):直接修改 tensor 变量
tensor4 = torch.rand(5, 3)
print('tensor3 + tensor4= ', tensor3 + tensor4)
print('tensor3 + tensor4= ', torch.add(tensor3, tensor4))
# 新声明一个 tensor 变量保存加法操作的结果
result = torch.empty(5, 3)
torch.add(tensor3, tensor4, out=result)
print('add result= ', result)
# 直接修改变量
tensor3.add_(tensor4)
print('tensor3= ', tensor3)

注意:可以改变 tensor 变量的操作都带有一个后缀_, 例如 x.copy_(y), x.t_() 都可以改变 x 变量
除了加法运算操作,对于 Tensor 的访问,和 Numpy 对数组类似,可以使用索引来访问某一维的数据,如下所示:

# 访问 tensor3 第一列数据
print(tensor3[:, 0])

对 Tensor 的尺寸修改,可以采用 torch.view() ,如下所示:

x = torch.randn(4, 4)
y = x.view(16)
# -1 表示给定列维度8之后,用16/8=2计算的另一维度数
z = x.view(-1, 8)
print("x = ",x)
print("y = ",y)
print("z = ",z)
print(x.size(), y.size(), z.size())

如果 tensor 仅有一个元素,可以采用 .item() 来获取类似 Python 中整数类型的数值:

x = torch.randn(1)
print(x)
print(x.item())

2.4 与 Numpy 数组的转换

Tensor 和 Numpy 的数组可以相互转换,并且两者转换后共享在 CPU 下的内存空间,即改变其中一个的数值,另一个变量也会随之改变。

2.4.1 Tensor 转换为 Numpy 数组

调用 tensor.numpy() 可以实现转换操作,例子如下所示:

a = torch.ones(5)
print(a)
b = a.numpy()
print(b)

2.4.2 Numpy 数组转换为 Tensor

转换的操作是调用 torch.from_numpy(numpy_array) 方法。例子如下所示:

import numpy as np
a = np.ones(5)
b = torch.from_numpy(a)
np.add(a, 1, out=a)
print(a)
print(b)

在 CPU 上,除了 CharTensor 外的所有 Tensor 类型变量,都支持和 Numpy数组的相互转换操作。

2.5 CUDA张量

Tensors 可以通过 .to 方法转换到不同的设备上,即 CPU 或者 GPU 上。例子如下所示:

# 当 CUDA 可用的时候,可用运行下方这段代码,采用 torch.device() 方法来改变 tensors 是否在 GPU 上进行计算操作
if torch.cuda.is_available():
    device = torch.device("cuda")  # 定义一个 CUDA 设备对象
    y = torch.ones_like(x, device=device)  # 显示创建在 GPU 上的一个 tensor
    x = x.to(device)                       # 也可以采用 .to("cuda") 
    z = x + y
    print(z)
    print(z.to("cpu", torch.double))       # .to() 方法也可以改变数值类型
tensor([0.2672], device='cuda:0')
tensor([0.2672], dtype=torch.float64)

输出结果,第一个结果就是在 GPU 上的结果,打印变量的时候会带有 device=‘cuda:0’,而第二个是在 CPU 上的变量。

总结

本周的学习围绕两大核心内容展开。首先,深入学习了李宏毅教授讲解的机器学习基础,明确了机器学习涵盖的三大任务类型:输出标量的回归任务、从给定选项中选择正确类别的分类任务以及生成具有结构输出如图像或文档的结构化学习任务。核心在于掌握训练模型的三个关键步骤:第一步是定义一个包含未知参数的模型函数,例如简单的线性模型;第二步是根据训练数据定义损失函数,用以量化模型预测值与真实标签之间的差距,常见的有平均绝对误差和均方误差;第三步是优化过程,主要使用梯度下降法迭代地更新模型参数,通过计算损失函数对参数的梯度并乘以学习率来调整参数,目标是找到最小化损失函数的参数组合,其中领域知识如识别数据周期性对改进模型设计至关重要。其次,系统学习了 PyTorch 的入门知识,重点在于理解张量作为核心数据结构的概念及其操作,包括使用不同方法创建张量、进行加法等运算、索引访问数据、使用 view 改变尺寸、以及与 NumPy 数组在 CPU 内存上的高效互转,并掌握了如何利用 .to 方法将张量迁移到 GPU 设备上以利用 CUDA 进行加速计算,显著提升运算效率。

Logo

技术共进,成长同行——讯飞AI开发者社区

更多推荐