深度学习修炼(一)—— 概述

简介: 本文讲述了如何用pytorch的基本概念以及一些简单的操作

1 转变

1.1 前言

在之前的机器学习中,我们都是讲解完知识,然后使用sklearn提供的API,然后疯狂传参调参。但是实际上底层的逻辑,比如它们为什么能这样,为什么有这样的效果,我们是不知道的。

在深度学习中就不一样了,我们必须掌握好数学这个画笔,用它规划出我们想要的神经网络。而对于颜料来说,各种深度学习框架已经提供了我们所需的各种颜料。我们要做的,就是利用不同的颜料,在空白的纸上,一笔一划画出我们所需的网络。

深度学习改变了传统互联网业务。第一次听到这个名词时可能大家都会对这方面的知识感到一头雾水,到底什么是深度学习?实际上,深度学习已经应用到生活中的点点滴滴了,比如我们熟知的自动无人驾驶,小爱同学音箱和其他的一些人工智能产品。在这个笔记中,你可以无需任何视频直接从头看到尾,也可以搭配任何一个深度学习的课程视频进行观看,当然,除了里面的代码部分,其他的对于所有的深度学习框架是通用的,代码部分主要用的是pytorch框架来书写的。

1.2 基本元素

在深度学习中,实际上最基本的元素就是张量。所以如何利用pytorch来创建一个张量成为我们第一个问题。在后面的学习中,我会告诉你为何张量很重要。

1.2.1 张量

在机器学习中,我们谈论过了线性代数的部分知识,当时我们讲到,0维叫标量,1维叫向量,2维叫矩阵,2维以上叫多维矩阵。

而实际上,在torch中其赋予了这些维度一个统一的名词,即张量。如果你学过Numpy,张量实际上就相当于Numpy中的adarray。由此我们不禁疑问,为何torch还要搞自己的这套方法呢?直接用Numpy的不好吗?

在大部分的学习框架中实际上都有属于自己的方法来创建张量,这是因为深度学习一般用来处理大量的数据,而仅仅用电脑的CPU硬件已经不能满足我们深度学习的算力了,为此,我们需要使用GPU来加速我们的算法,而Numpy是不支持GPU加速的,而深度学习框架的张量可以。

换而言之,在深度学习框架中的张量一般都可以很好地支持GPU加速运算,而Numpy仅仅支持CPU计算。

1.2.2 创建张量

在Pytorch中,张量的英文继承于TensorFlow深度学习框架中的张量Tensor。如果我们要利用最简单的方法来创建一个tensor,可以用列表来创建,如下:

import torch

tensor = torch.FloatTensor([[1, 2, 3], [4, 5, 6]])
print(f"张量为:{tensor}")

out:

张量为:tensor([[1., 2., 3.],

   [4., 5., 6.]])

实际上,torch提供了创建不同数据类型张量的方法,上述的是创建一个浮点数张量,所以无独有偶,我们可以尝试把Float改成Int,其可以为我们创建一个Int类型的常量。

torch.IntTensor([[1,2,3],[4,5,6]])

当然类似于Numpy,在Numpy中有ones,zeros等方法创建全1和全0向量,在torch也可以这么做。

torch.IntTensor(2,4).zero_()
torch.zeros((2,3,4))
torch.ones((2,3,4))

利用python的索引和切片,我们可以获取和修改一个张量中的任意一个元素。

A = torch.IntTensor([[1,2,3],[4,5,6]])
print(A[1][2])

前面我们不是说过可以利用GPU来加速张量吗?详情可以见下表:

Data type CPU tensor GPU tensor
32-bit floating point torch.FloatTensor torch.cuda.FloatTensor
64-bit floating point torch.DoubleTensor torch.cuda.DoubleTensor
16-bit floating point N/A torch.cuda.HalfTensor
8-bit integer (unsigned) torch.ByteTensor torch.cuda.ByteTensor
8-bit integer (signed) torch.CharTensor torch.cuda.CharTensor
16-bit integer (signed) torch.ShortTensor torch.cuda.ShortTensor
32-bit integer (signed) torch.IntTensor torch.cuda.IntTensor
64-bit integer (signed) torch.LongTensor torch.cuda.LongTensor

上面这表格里面包含的玩意就别背了,我都背不下来,没事多用用,忘记查就行,上面的方法还挺有规律的不是?

我们可能在平时学习python时不怎么关注内存,但是在深度学习中内存也是十分重要的。为此,torch提供了节省内存的方法。如你想对A张量的元素全部做绝对值操作,那么abs方法可以在原有的张量基础上在创建一个张量用于存放新的计算后的张量。而使用abs_方法则是在原有的张量上直接操作,把原有的张量做绝对值操作后直接覆盖。

就地操作可以节省一些内存,但由于会立即丢失历史记录,因此在计算导数时可能会出现问题。因此,不鼓励使用它们。

1.2.3 操纵张量

张量有了,我们就得会各种各样的操作,其中不乏就是加减乘除。为了下面的学习,我们当然需要先会一些操作了。

1.2.3.1 张量乘法

张量乘法就是我们在机器学习中谈到的矩阵——矩阵乘法。在pytorch中,我们使用mm(matrix multiplication)matmul方法来做这么一件事情。

import torch

A = torch.arange(12).reshape(3, 4)
B = torch.arange(12).reshape(4, 3)

print(f"两矩阵乘积为:{torch.mm(A, B)}")
print(f"两矩阵乘积为:{torch.matmul(A, B)}")

out:

两矩阵乘积为:tensor([[ 42, 48, 54],

   [114, 136, 158],
   [186, 224, 262]])

两矩阵乘积为:tensor([[ 42, 48, 54],

   [114, 136, 158],
   [186, 224, 262]])

如果是两个一维张量即向量相乘时,我们还可以使用dot方法。

import torch

A = torch.arange(12)
B = torch.arange(12)
print(f"两向量点积为:{torch.dot(A, B)}")

out:

两向量点积为:506

1.2.3.2 哈达玛积

如果你并不想做矩阵乘法,而是想要让两个矩阵对应元素相乘,那么使用运算符*即可达到这种效果。

import torch

A = torch.arange(12)
B = torch.arange(12)
print(A)
print(B)

print(f"哈达玛积为:{A*B}")
tensor([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])
tensor([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])
哈达玛积为:tensor([ 0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121])

1.2.3.3 降维

emm,实际上我觉得可以稍微偷懒,先把数据用sklearn中的PCA降维先降维掉,或者用特征选取先整好。当然深度学习它们不允许我这么干,它们通常都是把矩阵中的某些数据往轴上合并。如求和、求平均啥的。

python的内置函数sum()允许我们对张量内的元素求和。当前我们可以发现,通过求和,本来是一维张量,变成了0维的张量。

import torch

x = torch.arange(4, dtype=torch.float32)
print(f"x:{x}")
print(f"x_sum:{x.sum()}")

out:

x:tensor([0., 1., 2., 3.])
x_sum:6.0

明显地,这实际上就是一种降维的方法,调用求和函数会沿所有的轴降低张量的维度,使它变为一个标量;一维可以变0维,那么说明二维也能变一维,我们可以指定沿着哪个轴来通过求和降低维度。

import torch

A = torch.arange(12).reshape(3, 4)
A_sum_axis0 = A.sum(axis=0)
print(f"A_sum_axis0:{A_sum_axis0}")
print(f"A_sum_axis0_shape:{A_sum_axis0.shape}")

out:

A_sum_axis0:tensor([12, 15, 18, 21])
A_sum_axis0_shape:torch.Size([4])

对比矩阵A,我们可以发现如果沿着0轴(行)求和,那么实际上就是把该列所有的元素全部相加,加到该列的第0个元素上去。

同样的,如果指定axis = 1,那么将沿着列求和,那么实际上就是把每行的所有元素相加,加到该行的第0个元素上去。

A = torch.arange(12).reshape(3, 4)
A_sum_axis1 = A.sum(axis=1)
print(f"A_sum_axis1:{A_sum_axis1}")
print(f"A_sum_axis1_shape:{A_sum_axis1.shape}")

out:

A_sum_axis1:tensor([ 6, 22, 38])
A_sum_axis1_shape:torch.Size([3])

axis = 0按照行,可以理解为把“行”给抹去只剩1行,也就是上下压扁。
axis = 1按照列,可以理解为把“列”给抹去只剩1列,也就是左右压扁。

当然,如果你又对行又对列求和,那么实际上就是对矩阵的所有元素求和。

import torch

A = torch.arange(12).reshape(3, 4)
print(A.sum(axis=[0, 1]))  # 相当于 A.sum()

out:

tensor(66)

也许有人说不喜欢通过求和加到某条轴上这种方式去降维,那你可以选择通过求平均值然后把平均值写在某条轴上来降维。求平均值有两种方法,一种是调用python内置函数mean(),另外一种就是用sum()/numel,这实际上也是一种求平均值的方法,但是,我相信你不会那么蠢选择后者是吧。

1.2.3.4 转置

用张量自带的T方法即可完成转置。

import torch

A = torch.arange(12).reshape(3,4)
print(A)
print(A.T)

out:

tensor([[ 0, 1, 2, 3],

   [ 4,  5,  6,  7],
   [ 8,  9, 10, 11]])

tensor([[ 0, 4, 8],

   [ 1,  5,  9],
   [ 2,  6, 10],
   [ 3,  7, 11]])

1.2.3.5 范数

如果要计算一个向量的$L_2$范数,可以使用norm来计算。

import torch

u = torch.tensor([3.0, -4.0])
print(torch.norm(u))

out:

tensor(5.)

如果是$L_1$范数,他表示为向量元素的绝对值之和。这么说,我们求$L_1$范数可以这么求:先求每个元素的绝对值,然后再求和。

import torch

u = torch.tensor([3.0, -4.0])
print(torch.abs(u).sum())

out:

tensor(7.)

1.2.3.6 拼接张量

如果想要拼接n个张量,可以使用torch.cat方法。其中dim = 0,则n个张量按竖轴拼接;若dim = 1,则按横轴拼接。

import torch

tensor = torch.arange(4).reshape(2, 2)
t1 = torch.cat([tensor, tensor, tensor], dim=0)
print(t1)

out:

tensor([[0, 1],

   [2, 3],
   [0, 1],
   [2, 3],
   [0, 1],
   [2, 3]])

1.2.4 张量属性

我们用shape查看张量形状,用dtype查看张量数据类型,用device查看张量存储设备。

import torch

tensor = torch.rand(3, 4)

print(f"shape of tensor:{tensor.shape}")
print(f"shape of tensor:{tensor.dtype}")
print(f"Device tensor is stored on:{tensor.device}")

out:

shape of tensor:torch.Size([3, 4])
shape of tensor:torch.float32
Device tensor is stored on:cpu

如果你的张量中只有一个元素,即单元素张量,那么使用tensor.item()方法可以使其从tensor类型变为int、float等类型。具体是什么类型看张量中的单元素而定。

import torch

A = torch.arange(12).reshape(3,4)
agg = A.sum()
agg_item = agg.item()
print(agg_item,type(agg_item))

out:

66

1.2.5 张量和Numpy

1.2.5.1 张量变Numpy

如果想要使一个Tensor变为adarray,则调用tensor自身的numpy方法即可。

import torch

t = torch.ones(5)
print(t)
n = t.numpy()
print(n)

out:

tensor([1., 1., 1., 1., 1.])
[1. 1. 1. 1. 1.]

1.2.5.2 Numpy变张量

如果想要使一个adarray变为Tensor,则调用torch的from_numpy方法即可。

import torch
import numpy as np

n = np.ones(5)
t = torch.from_numpy(n)
print(t)

out:

tensor([1., 1., 1., 1., 1.], dtype=torch.float64)

1.3 后话

从机器学习到深度学习思路要学会转变了,我们不再是那个调包侠了,我们也能利用学到的知识从0搭建一个网络了。这是非常重要的一个点,在后面的学习中你会慢慢适应的。这一讲就到这里吧。

相关实践学习
部署Stable Diffusion玩转AI绘画(GPU云服务器)
本实验通过在ECS上从零开始部署Stable Diffusion来进行AI绘画创作,开启AIGC盲盒。
目录
相关文章
|
1月前
|
机器学习/深度学习 存储 自然语言处理
深度学习入门:循环神经网络------RNN概述,词嵌入层,循环网络层及案例实践!(万字详解!)
深度学习入门:循环神经网络------RNN概述,词嵌入层,循环网络层及案例实践!(万字详解!)
|
1月前
|
机器学习/深度学习 PyTorch API
深度学习入门:卷积神经网络 | CNN概述,图像基础知识,卷积层,池化层(超详解!!!)
深度学习入门:卷积神经网络 | CNN概述,图像基础知识,卷积层,池化层(超详解!!!)
|
3月前
|
机器学习/深度学习 人工智能 自然语言处理
【深度学习】深度学习的概述及应用,附带代码示例
深度学习(Deep Learning,简称DL)是机器学习领域中的一个重要分支,其目标是通过模拟人脑神经网络的工作机制,构建多层次的抽象特征表示,使机器能够自动从原始数据中提取关键信息,从而实现高精度的任务执行。深度学习通过多层神经网络结构及其训练方式,实现了从低级像素级别到高级概念级别的递进式知识层次。 深度学习的主要组件包括输入层、隐藏层和输出层。隐藏层的数量和层数决定了模型的复杂度和表达能力。在训练过程中,权重更新和梯度下降法是关键步骤,目的是最小化损失函数,提高预测精度。深度学习主要基于反向传播算法(BP Algorithm)来优化模型参数,通过正向传播、损失计算、反向传播和梯度下降等
176 8
|
3月前
|
机器学习/深度学习 人工智能 自然语言处理
【深度学习】AudioLM音频生成模型概述及应用场景,项目实践及案例分析
AudioLM(Audio Language Model)是一种基于深度学习的音频生成模型,它使用自回归或变分自回归的方法来生成连续的音频信号。这类模型通常建立在Transformer架构或者类似的序列到序列(Seq2Seq)框架上,通过学习大量音频数据中的统计规律,能够生成具有高保真度和创造性的音频片段。AudioLM模型不仅能够合成音乐、语音,还能生成自然界的声音、环境噪声等,其应用广泛,涵盖了娱乐、教育、辅助技术、内容创作等多个领域。
102 1
|
6月前
|
机器学习/深度学习 PyTorch TensorFlow
【TensorFlow】深度学习框架概述&TensorFlow环境配置
【1月更文挑战第26天】【TensorFlow】深度学习框架概述&TensorFlow环境配置
|
6月前
|
机器学习/深度学习 分布式计算 搜索推荐
深度学习入门:一篇概述深度学习的文章
深度学习入门:一篇概述深度学习的文章
|
机器学习/深度学习 TensorFlow 算法框架/工具
深度学习概述(二)
深度学习概述(二)
103 0
|
机器学习/深度学习 人工智能 算法
深度学习概述(一)
深度学习概述(一)
104 0
|
机器学习/深度学习 存储 算法
【深度学习之模型优化】模型剪枝、模型量化、知识蒸馏概述
【深度学习之模型优化】模型剪枝、模型量化、知识蒸馏概述
1644 0
【深度学习之模型优化】模型剪枝、模型量化、知识蒸馏概述
|
机器学习/深度学习 人工智能 资源调度
水很深的深度学习-Task01深度学习概述与数学基础
人工智能分类:强人工智能、弱人工智能、超级人工智能 机器学习分类:有监督学习、无监督学习、强化学习
136 0
水很深的深度学习-Task01深度学习概述与数学基础
下一篇
无影云桌面