10
0
0

深度学习概论

2026-07-22
2026-07-24

机器学习-深度学习

思维导图

深度学习概览-YAcW.png

为什么学习深度学习?

1.旧的技术不能解决当前的问题

2.旧的技术解决当前问题过于复杂(安全)

深度学习的模块

文本 - RNN - 循环神经网络 - 词嵌入层+循环层+全连接层

图像 - CNN - 卷积神经网络 - 卷积层+池化层+全连接层

全连接层 - ANN - 人工神经网络

人工神经网络 - 张量

核心点提炼

X * + Z(预测值) Loss(损失) 求导->梯度 --------------->正向传播

W B Y(真实值) <---------------反向传播(梯度更新公式:W新 = W旧 - 学习率*梯度)

神经元( 信息的求和 | 激活函数 )

全连接层 = 当前层的每一个神经元都由上一层的所有神经元进行连接

深度学习的特点

1.由神经网络+神经搭建而成

​ 输入层(特征) ---- 隐藏层 ---- 输出层

  1. 特征工程不需要人工处理,而是由算法自动算法
  2. 大数据 + 算力(可以使用GPU加速)
  3. 可解释性差,隐藏层是一个黑盒子,至于为什么是3层,5层,18层,当前业界公认无法解释

张量的使用

张量的创建

# 基于小写的tensor
指定数据 - torch.tensor
# 基于大写的Tensor
指定数据 + 指定维度 - torch.Tensor
#基于指定的类型进行创建 int16 32 64  float16 32 64  <->   short int long half float double
torch.IntTensor(2,3)   IntTensor([1,2,3])  

线性张量

torch.arange(起始,结束,步长) -> 包左不包右
torch.linspace(起始,结束,划分数量) -> 包左包右

随机张量

随机种子:
看 - torch.initital_seed()
改 - torch.manual_seed()
随机数
0-1 - torch.rand()
-3-3 - torch.randn()
随机整数 
torch.randint(起始,结束,尺寸) ->包左不包右

全0全1

ones(尺寸)  通过尺寸创建
ones_like(张量)  通过张量的形状创建
zeros(尺寸) 通过尺寸创建
zeros_like(张量) 通过张量的形状创建

创建指定张量

torch.full(size,填充值)
torch.full_like(张量,填充值)

数据类型转换

data = torch.tensor([1,2,3])
data.type(指定的类型)  #int16 int32 int64 float16 float32 float64.....
data.type(torch.IntTensor) #了解即可
data.half()   data.int() #了解即可

tensor和numpy的转换

tensor -> numpy 
tensor = torch.tensor([1,2,3])
tensor = tensor.numpy()#转换,共享
tensor = tensor.numpy().copy()#转换,不共享

numpy -> tensor
tensor = torch.form_numpy(numpy)#转换,共享
tensor = torch.form_numpy(numpy.copy)#转换,共享
tensor = torch.tensor(numpy)#创建,不共享

从一个数据的tensor中取出值
data1 = tensor = torch.tensor(1)
data2 = tensor = torch.tensor([1])
data1.item()

简单计算

加 减 乘 除 负号

add sub mul div neg

add_ sub_ mul_ div_ neg_ 带下划线表示修改原数据

掌握 :+ - * /

# 掌握:
# 1.+ - * /
# 2.pytorch中,所有带_都表示更新原数据
import torch
# 加减乘除取负号
# add   sub   mul   div  neg
# +    -    *    /
# 1.准备数据
data = torch.tensor([[-1, 2], [3, 4], [5, 6]])
# 2.1-加法:加常数
t1 = torch.tensor([[1, 1], [2, 2], [3, 3]])
print(data + 1)
# 2.2-加法:加tensor
print(data + t1)
print(t1.add(data))  # 同上
# 2.3把data加到t1上,然后更新t1
t1.add_(data)
print(t1)
# 其他运算演示
print(data-t1)
print(data.sub(t1))#同上
print(data*t1)
print(data.mul(t1))#同上
print(data/t1)
print(data.div(t1))#同上
# 3.取负号
print(data.neg())
print(data*-1)#同上


点积点乘

点乘 - mul *

​ 两个形状相同的张量相乘=每个位置相乘

点积(没有交换律) - matmul @

​ 1.前提:两个张量能点积的 = a的列等于b的行

​ 2.过程:a的行 * b的列

​ 3.结果:a行b列

掌握 :@ matmul

# 掌握: @
import torch
t1 = torch.tensor([[1,2],[2,3]])
t2 = torch.tensor([[2,2],[3,3]])
# 点乘
print(t1*t2)
print(t1.mul(t2))

t3 = torch.tensor([[1,2],[2,3],[3,4]])
# 点积
# print(t2@t3)
print(t3@t2)
# print(torch.matmul(t2,t3))
print(torch.matmul(t3,t2))


# 补充:
# print(t3.sign()) #带符号的全1
# print(t3.square()) #平方
# print(t3.fmod(2)) #取余
# ......


运算函数

1.求和 sum :dim表示第几维进行求和

2.平均值mean/最大值max/最小值min

3.开方sqrt/平方square/幂pow/绝对值abs\absolute

4.指数exp

5.对数log/log2/log10

掌握 sum

# 掌握:sum
import torch

# 0.准备数据
data = torch.tensor(
    # 第0维度:将下面括号内的数据进行求和,合并成1条数据
    [
        # 第1维度:将下面括号内的数据进行求和,合并成1条数据
        [1,2,3],
        [4,5,6]
    ]
)


# 1.求和sum - 维度
print(data.sum(dim=0)) #第0维,列求和
print(data.sum(dim=1)) #第1维,行求和
# print(data.sum(dim=2)) #?报错!!!超出dim区间!!
print(data.sum()) #整个求和

# 2.平均、最大值、最小值
# (1+2+3+4+5+6)/6 计算会有小数,所以需要的是float类型,但是现在是int类型
data = data.type(torch.float32)
print(data.mean()) #平均值一般都不是整数,所以只有float类型才能进行平均值的计算
print(data.max())
print(data.min())

# 3.开方  平方  幂  绝对值
data.sqrt_()  #开方
print(data)
data.square_()  #平方
print(data)
data.pow_(2) #2次幂 === 平方
print(data)
data = data*-1
print('负1的data',data)
data.abs_()  # 绝对值
data.absolute_()  # 绝对值
print('绝对值data',data)

# 4.指数e
print(data.exp())

# 5.对数
print(data.log())
print(data.log2())
print(data.log10())

索引使用

掌握 所有(除了多维索引)

0.准备数据

data = torch.randint(1,10,(3,4))

# 第0维
# [ 
#     第1维
#     [5, 6, 2, 4, 2],
#     [4, 7, 3, 8, 2],
#     [8, 1, 3, 3, 1],
#     [5, 4, 7, 9, 9]
# ]

1.简单行列索引

data[0](语法糖) - 人话:取第0行 - 逻辑:取0维的第一个

data[0,:] (效果同上)

data[:,0] - 人话:取第1列 - 逻辑:取0维所有,取1维第一

2.列表索引

人话:[[行索引],[列索引]]]

逻辑:[[0维索引],[1维索引]]

data[[0,1],[1,2]] #取的是(0,1),(1,2)

data[[1,3],[2,4]] #取的是(1,2),(3,4)

3.范围索引(切片)

data[:3,:4] #取前2行,前3列

4.布尔索引

data>5 #得到布尔值索引

data[data>5] #获取原数据布尔值所引为True的数据

5.多维索引

mul_data = torch.randint(1,10,(3,4,5))

# 第0维数据([]里面的内容是第0维数据)-0轴 - 3个数据
# [
#     第1维数据([]里面的内容是第1维数据)-1轴 - 4个数据
#     [
#         第2维数据([]里面的内容是第2维数据)-2轴 -5数据
#         [1, 6, 7, 2, 1],
#         [6, 6, 4, 5, 9],
#         [7, 2, 5, 5, 7],
#         [6, 9, 8, 9, 1]
#     ],
#     [
#         [5, 1, 6, 1, 8],
#         [7, 8, 9, 1, 1],
#         [3, 5, 2, 4, 3],
#         [5, 7, 8, 2, 6]
#     ],
#     [
#         [5, 6, 1, 7, 1],
#         [8, 6, 9, 8, 8],
#         [1, 3, 6, 2, 9],
#         [9, 9, 5, 2, 6]
#     ]
# ]
# 需求1:取出0轴第1个数据
#     [
#         [1, 6, 7, 2, 1],
#         [6, 6, 4, 5, 9],
#         [7, 2, 5, 5, 7],
#         [6, 9, 8, 9, 1]
#     ]
# 需求2:取出1轴第1个数据
# 理解:取出0轴所有的数据,1轴第1个数据
# 过程:0轴第1个1轴第1个数据 0轴第2个1轴第1个数据 0轴第3个1轴第1个数据
#     [
#         [1, 6, 7, 2, 1]
#     ]
#     [
#         [5, 1, 6, 1, 8]
#     ],
#     [
#         [5, 6, 1, 7, 1]
#     ]
# 需求3:取出2轴第1个数据
# 翻译:取出0轴所有的数据,取出1轴所有的数据,取出2轴的第1个数据
# 说明:
#   (
#    0轴第"1"个1轴第"1"个,
#    0轴第"1"个1轴第"2"个
#    0轴第"1"个1轴第"3"个
#    0轴第"1"个1轴第"4"个
#    )
#    结果: [1,6,7,6]
#   (
#    0轴第"2"个1轴第"1"个,
#    0轴第"2"个1轴第"2"个
#    0轴第"2"个1轴第"3"个
#    0轴第"2"个1轴第"4"个
#    )
#    结果: [5,7,3,5]
#   (
#    0轴第"3"个1轴第"1"个,
#    0轴第"3"个1轴第"2"个
#    0轴第"3"个1轴第"3"个
#    0轴第"3"个1轴第"4"个
#    )
#    结果:[5,8,1,9]
# 最终结果:[[1,6,7,6],[5,7,3,5],[5,8,1,9]]
# 总结:多维索引每一个维度都要考虑到,如果没有明确说明要或者不要,那表示全都要!!!

张量形状改变

掌握:reshape squeeze unsqueeze transpose permute

reshape 不改变原数据的前提下,改变形状

squeeze降维 - 在原数据基础上将所有维度为1删除

unsqueeze升维 - 在原数据基础上提升一个维度

transpose交换任意两个维度

permute交换任意个数的维度

[了解] view改变形状(数据保持连续性) + contiguous(修改数据内存,保持数据连续)

import torch
# 0.准备数据
data = torch.tensor([[1,2,3],[4,5,6]])
# 1.使用reshape进行数据的修改(2,3 -> 1,6)
t1 = data.reshape(1,6) # [[1,2,3],[4,5,6]]->[[1, 2, 3, 4, 5, 6]]
print(t1,t1.data_ptr(),t1.stride()) #data - pointer 数据指针,stride表示在内存中读取数据的步长

# 2.使用reshape进行数据的修改(2,3 -> 1,?)
t2 = data.reshape(1,-1) #会自动计算-1变成6
print(t2,t2.data_ptr(),t2.stride()) #data - pointer 数据指针,stride表示在内存中读取数据的步长

# 3.使用reshape进行数据的修改(2,3 -> 2,?)
t3 = data.reshape(3,-1) #会自动计算-1变成2
print(t3,t3.data_ptr(),t3.stride()) #data - pointer 数据指针,stride表示在内存中读取数据的步长
## 4.使用reshape进行数据的修改(2,3 -> 4,2)
# t4 = data.reshape(4,2) #报错
# print(t4)
# reshape可以在满足前提的情况下修改数据
# 【拓展】张量数据创建的时候,在底层就已经分类内存,将对应的值写入内存中
# 1.张量数据不变 ===> 内存中的内容没有发生变化
# |----|
# |  1 |
# |----|
# |----|
# |  2 |
# |----|
# |----|
# |  3 |
# |----|
# |----|
# |  4 |
# |----|
# |----|
# |  5 |
# |----|
# |----|
# |  6 |
# |----|
# 2.数据不变,为什么形状可以变化====>步长计算公式——》不同形状下的数据应该是什么样!!

张量的拼接

掌握 全部

cat - 不会提升维度 - 除了拼接的维度不一样,其他维度必须一样

stack - 会提升维度 - 所有数据的维度必须完全一致

总结:

cat - 其他维度不变,拼接维度做加法

stack - 其他维度不变,升哪个维度,哪个维度就等于拼接的数据条数

# 给豆包发消息:图片(张量)+文字(张量) = 1条消息(张量)

import torch
# -------------------------------------cat拼接(不会提升维度数)
# 要求:两个数据进行指定维度的拼接,除了指定的维度数可以不一样,其他数量必须一样
# 0.准备数据
data1 = torch.tensor([[1,2,3],[4,5,6]]) #2行3列  dim0=2  dim1=3
data2 = torch.tensor([[1,2,3],[4,5,6],[4,5,6]]) #3行3列  dim0=2  dim1=3
# 1.按照dim=0进行拼接data1和data2
data = torch.cat([data1,data2],dim=0)
print(data)

# 2.按照dim=1进行拼接data1和data2
data3 = torch.tensor([[1,2,3,4,5],[1,2,3,4,5]]) #2行5列
data = torch.cat([data1,data3],dim=1)
print(data)
# -------------------------------------stack拼接(会提升维度数)
# 0.准备数据(维度必须完全一致)
data4 = torch.tensor([[1,2,3],[4,5,6]]) #2,3
data5 = torch.tensor([[1,2,3],[4,5,6]]) #2,3
data6 = torch.tensor([[1,2,3],[4,5,6]]) #2,3

data = torch.stack([data4,data5,data6],dim=0) #0维进行提升
print(data.shape)#[3],2,3
# 2,3 + 2,3 + 2,3  +dim =0  _>  3,2,3
data = torch.stack([data4,data5,data6],dim=1) #1维进行提升
print(data.shape)#2,[3],3
# 2,3 + 2,3 + 2,3  +dim =1  _>  2,3,3
data = torch.stack([data4,data5,data6],dim=2) #2维进行提升
print(data.shape)#2,3,[3]
# 2,3 + 2,3 + 2,3  +dim =2  _>  2,3,3

# 总结:其他维度不变,升哪个维度,哪个维度就等于数据的条数

# 需求:2行3列+2行3列
# 如果dim = 0  ->  2行3列+2行3列  = [2]个2行3列
# 如果dim = 1  ->  2行3列+2行3列  = 2个[2]行3列
# 如果dim = 2  ->  2行3列+2行3列  = 2个[3]行[2]列
# 都是2行3列进行拼接,指定哪个维度,哪个唯独就是新提升上来的
# 2,3 + 2,3 +dim=0 = >   【2】,2,3
# 2,3 + 2,3 +dim=1= >     2,【2】,3
# 2,3 + 2,3 +dim=2= >     2,3,【2】

自动微分

函数.backward()

函数必须是设置了require_grad属性的相关函数

作用:求导

x = torch.linspace(-20,20,1000,requires_grad=True)
y = torch.sigmoid(x)  #定义一个函数
y.sum().backward()    #对函数求导

自动微分的使用

X = torch.ones(2,5)

W = torch.randn(5,3)

B = torch.randn(3)

Z = X@W +B 

Y = torch.zeros(2,3)

loss_fn = MSELoss()
loss = loss_fn(Z,Y)

#自动微分
loss.sum().backward()

w.grad   b.grad

模拟线性回归

1.准备数据 make_regressor( 样本数量,特征数量,标签数量,噪声,coef,bias )

2.数据->张量->数据集->数据加载器

3.训练模型

​ 准备model

​ 准备优化器optimizer

3.1模型预测

y_pre = model(x)

3.2定义损失函数

loss_fn = MSELoss()

3.3计算损失

loss = loss_fn(y_pre,y)

3.4自动微分

loss.backward()

3.5更新梯度

optimizer.step()

3.6清空梯度

optimizer.zero_grad()

3遍起步

import torch
from sklearn.datasets import make_regression #创建线性回归数据
from torch.utils.data import TensorDataset,DataLoader #数据集/数据加载器
import matplotlib.pyplot as plt
import matplotlib
# matplotlib中文支持
matplotlib.rcParams['font.sans-serif'] = ['SimHei']
matplotlib.rcParams['axes.unicode_minus'] = False
# 1.创建数据
def create_data():
    # Z = KX +B  k斜率  b偏置
    # 已知X 已知Y - 用于训练模型,让模型可以进行预测
    # 已知k 已知b - 用于检测最终我们的模型预测结果的
    # bias = 3,x,y,coef?
    x,y,coef = make_regression(
        n_samples = 100,    #样本数量
        n_features = 1,     #特征数量
        n_targets = 1,      #标签数量
        bias = 3,           #偏置的值(自定义)
        noise = 10,         #噪声(如果没噪声就成了完美直线了)
        coef=True,          #是否计算斜率
        random_state=3
    )
    # print(x)
    # print(y.reshape(-1,1))
    print(coef) # 斜率:27.478050549563925
    # bias = 3  # 偏置:3

    return x,y.reshape(-1,1),coef

# 2.模型训练
def train(x,y,coef):
    # 数据->张量->数据集->数据加载器(多轮训练的依赖)
    # x特征,y标签 -> coef bias
    # 1.数据(100)-> 张量
    x = torch.tensor(x,dtype=torch.float32)
    y = torch.tensor(y,dtype=torch.float32)
    # 2.张量 -> 数据集
    dataset = TensorDataset(x,y)
    # 3.数据集 -> 数据加载器
    # 参数说明:
    # 1.数据集 - 100条数据
    # 2.批次训练数据量 - 16条数据,每次从100条中取16条,训练7次才能结束
    # 3.数据是否随机
    dataloader = DataLoader(dataset,batch_size=16,shuffle=True)
    # # 查看数据
    # for x_train,y_train in dataloader:
    #     print(x_train.shape)
    #     print(y_train.shape)
    # 4.模型训练
    # 0.准备工作
    # 模型创建 - 参数说明:1.特征数量  2.标签数量
    model = torch.nn.Linear(in_features=1,out_features=1)
    # 优化器创建 - 参数说明:1.模型的参数  2.学习率
    optimizer = torch.optim.SGD(params=model.parameters(),lr=0.01)
    # 5.计算损失
    # 5.1 - 总损失 - 记录每一批次的损失(画图)
    loss_list = []
    # 100轮 = 每轮7次 = 700批次
    for i in range(100):
        # 5.2 - 每一轮的详细损失:总损失 ,平均损失
        total_loss,train_count = 0,0
        # 训练7次,每批16条数据 / 一轮  100->16/16/16/16/16/16/4
        for x_train, y_train in dataloader:
           # -----------------------------------前向传播
           # 1.模型预测
           y_pre = model(x_train)
           # 2.损失函数
           loss_fn = torch.nn.MSELoss()
           loss = loss_fn(y_pre, y_train)
           # loss_list.append(loss) #记录到损失的列表中(记每一次,100*7)
           total_loss += loss.item() #记录每一轮的总损失
           train_count += 1 #几轮训练的次数
           # -----------------------------------反向传播
           # 3.自动微分:获取到梯度
           loss.backward()
           # 4.更新梯度:优化器实现
           optimizer.step()
           # 5.梯度清零
           optimizer.zero_grad()
        print(f"第{i+1}轮训练,平均损失:{total_loss/train_count}")
        loss_list.append(total_loss/train_count) #每一轮的平均损失
    #训练结束:训练结果在模型身上
    print(f"训练结束,查看模型结果:{model.state_dict()}")
    print(f"训练结束,查看真实结果:{coef},3")

    # 6.数据可视化
    print(len(loss_list))
    # 6.1绘制损失下降的曲线  - 关于损失的
    # plt.scatter(range(len(loss_list)),loss_list)
    # plt.title("损失下降曲线")
    # plt.xlabel("训练次数")
    # plt.ylabel("损失值")
    # plt.show()
    # 6.2绘制样本数据的点
    plt.scatter(x,y)
    # 6.3绘制真实的直线
    # x , y = coef*x+3
    #细节点1-报错原因:'numpy.ndarray' and 'Tensor' -> numpy数据不能和tensor数据进行运算,但是tensor数据可以和numpy数据进行运算
    plt.plot(x,x*coef+3,color="red")
    # 6.4绘制预测的直线
    #细节点2-报错原因:因为i不能直接转numpy需要先detach()再numpy()
    plt.plot(x,[i.detach().numpy() for i in model(x)],color="green")
    plt.title("预测结果对比")
    plt.xlabel("特征值")
    plt.ylabel("标签值")
    plt.legend(["样本数据","真实直线","预测直线"])
    plt.show()


if __name__ == '__main__':
    # 已知x特征 y标签 以及真实的斜率/偏置
    x,y,coef = create_data()
    # 模型训练(给你x,y,自己算W B)
    train(x,y,coef)


# 模型训练总结:(神经元的加权求和)
# 1.数据准备:数据->张量->数据集->数据加载器
# 2.模型准备:模型创建 / 优化器创建
# 3.模型训练:训练几轮?每轮训几批?每批训几条?
# 4.训练流程:正向(前向)传播 / 反向传播
# 前向传播:模型预测/损失函数/损失
# 反向传播:自动微分/更新梯度/梯度清零

# 神经元(加权求和|激活函数)


# 绘图:
# 统计损失,看一下损失的变化 ,预测直线和真实直线以及样本之间的差异

支持与分享

如果这篇文章对你有帮助,欢迎分享给更多人或者给予支持!