第二次作业:深度学习基础

本博客为OUC2022秋季软件工程第二周作业——深度学习基础

目录

【第一部分】视频学习心得及问题总结 

【第二部分】代码练习 

2.1 pytorch 基础练习

1. 定义数据

2. 定义操作

 2.2 螺旋数据分类

1. 构建线性模型分类

2. 构建两层神经网络分类


【第一部分】视频学习心得及问题总结 

朱甲文

学习心得:

        通过对视频的观看以及学习,我大致了解了机器学习和人工智能的发展历程,认识到了当今世界人工智能行业的发展状况以及发展趋势。目前,人工智能应用性极强,可以与多种产业相结合。同时,我学到了机器学习的步骤,也就是模型、策略和算法三部分,了解了监督学习和无监督学习的区别。通过进一步的学习,我也接触到了比机器学习更深的层面——深度学习,相较于传统的机器学习,深度学习的泛化和学习能力更强,也是目前广泛应用的技术之一。

        在第二个视频里,老师讲解了一些神经网络的基础知识,我学习了神经网络的结构以及多种激活函数和感知器,还学到了几种常见的算法,例如反向传播算法和梯度下降法,老师也介绍了自编码器和受限玻尔兹曼机等内容,这是我以前学习神经网络基础没有了解过的知识,让人受益匪浅。同时,我也存在着一些问题。

问题:

1、自编码器应最小化的目标函数是如何得出的?

2、对于受限玻尔兹曼机条件概率建模的推导过程不清晰,如何推导出激活函数是sigmoid?

赵志豪

学习心得:

机器学习问题可以分为回归、分类、聚类三大类;

1.传统机器学习算法大多较为简单,同时在训练大量数据时可能不够准确。以K-最近邻算法为例,该算法实现简单,预测的精度一般也较高,缺点在于对预测集的每个样本都需要计算它和每个训练样本的相似度,计算量较大,在训练集很大的时候影响算法性能。

2.深度学习是机器学习领域中一个新的研究方向,它被引入机器学习来用于研究人工智能。经典的深度学习模型有卷积神经网络、DBN和堆栈自编码网络模型等。相对于传统机器学习,深度学习有以下几个优点:

(1)学习能力强;

(2)覆盖范围广,适应性好

(3)数据驱动,上限高

(4)出色的可移植性

同时,由于深度学习需要大数据支撑,为保证算法的实时性,需要更高的并行编程技巧和更多更好的硬件支持。因此,只有一些经济实力比较强大的科研机构或企业,才能够用深度学习来做一些前沿而实用的应用。

3.单层感知机是二分类的线性分类模型,输入是被感知数据集的特征向量,输出时数据集的类别{+1,-1}。其在使用时,外部系统将输入数据变换成单层感知机接受的值域,之后外部系统将合法的输入数据输入到单层感知机,然后单层感知机利用已有模型计算结果,接着单层感知机输出数据,最后外部系统接收输出数据并使用。

问题:

1.为什么梯度消失可以通过使用激活函数 Relu、leakrelu、elu等来尝试解决?

2.反向传播BP算法如何训练多层感知机各层间的连接权值?

3.传统机器学习在什么情况下优于深度学习?

 钟杰聪

学习心得:

        在观看了学习视频之后,我对深度学习有了更深层次的了解。首先,机器学习是实现人工智能的一种途径,深度学习是实现机器学习的一种方法。其次,深度学习有利有弊,比如说深度学习有稳定性差、可调试性差、参数不透明、机器偏见、增量性差、推理能力差的六大缺点,但也有对数据有学习时间短、强大的拟合能力、具有推断能力、表达能力十分强大等优点。最后,我还通过视频了解到深度学习使用级联的多层(非线性)处理单元,以及受大脑结构和功能(神经元)启发的算法;也知道了深度学习分为监督学习和无监督学习;还了解到了神经网络的误差反向传播,梯度下降和消失等相关知识,之后还了解到了深度学习的逐层预训练,自编码器和受限玻尔兹曼机等相关知识。在学习完深度学习的基本知识后,我认为深度学习在未来有很大的发展空间,但是若要从事相关职业,需要有强大的数学基础和算法理解能力。

问题:

1.深度学习如今能成熟地应用在那些方面,未来又能应用于什么方面?

2.从深度学习的发展历史来看,许多次深度学习的突破都是因为新算法的发明,是否可以说明深度学习的发展重点在于算法的研究和改善?现在比较完善的算法有哪些呢?

李浩 

学习心得:

        虽然人工智能行业已经发展了许多年,但现在仍然算是行业风口,由于视频比较老,我去查了一下今年的数据,发现2022年,仅我国人工智能人才缺口就高达五百万人,还需要更多的人才投入该行业。

关于神经网络,全程看下来最大的感受就是尽管整个过程很曲折,但一直处于上升趋势,而且不论何时,都需要优秀的数学基础,所以在进行专业性的学习同时,要兼顾基础学科,不能有所偏废。

问题:

        讲师讲的还是比较清晰的,而且只是一些基本概念,最大的问题就是数学原理部分需要花费时间去理解。

赵吉林

学习心得:

  1. 介绍了一下人工智能和机器学习的大环境:我国在17年就实施了人工智能的人才战略。美国的人工智能在企业和高校里占比非常大,我国还需要努力。人工智能的起源:达特茅斯会议,图灵测试
  2. 人工智能的发展:经过了萌芽期、启动期、消沉期、突破期、发展期、高速发展阶段。
  3. 机器学习:主要就是学习模型、策略和算法。对模型分类,根据数据标记分为监督学习和无监督学习,前者标本具有标记,用于预测数据标记,后者样本没有标记,可以用来描述数据,还有特殊的半监督学习和强化学习。
  4. 深度学习的应用研究:视觉和语言,深度学习的理论研究:从“能“到”不能“。“不能“:①算法不稳定,容易被“攻击”。②模型复杂度高,难以纠错和调试。③模型层级符合程度高,参数不透明。④端到端的训练方式对数据依赖性强,模型增量性差。⑤专注直观感知类问题,对开放性推理问题无能为力。⑥人类知识无法有效引入进行监督,机器偏见难以避免。需要注意的是,算法依赖于大数据,但数据本身不可能是中立的,它是从真实社会中抽取的,必然会带有社会固有的不平等、排斥性和歧视
  5. 神经网络的参数学习:误差反向传播。梯度和梯度下降,参数沿负梯度方向更新可以是函数值下降。复合函数的链式求导,残差是损失函数在某个结点的偏导。深层神经网络的问题:梯度消失,误差通过梯度传播,越传越小。解决方法:全局最优解(凸二次规划),无需调参,基于支持向量,小样本训练。

看完两个视频,对于人工智能和机器学习有了初步的认识和了解,对数学相关的能力要求很高。

问题:对能量这个词还是不太理解,受限玻尔兹曼机的能量分布看不懂。

石昱杲 

学习心得:

        从影片中学到了人工智能起源于1956年的达特茅斯会议,同时,人工智能存在三个层面:计算智能,感知智能,认知智能。其中计算智能的典型例子是人工智能与人类棋手的博弈,感知智能则更加贴近我们的生活,而认知智能就涉及到深度思考领域。目前,人工智能已经运用于各个行业的各个领域。

问题:

1.目前,人工智能已经基本实现计算,感知智能,而在人类赖以生存的认知层面,机器学习是否能完全超过人类?人类是否需要像“基因锁”那样为人工智能设立技术上的枷锁,而不仅仅是依赖机器人定律?

2.现阶段,人工智能的热门行业有哪些?需要的基础能力又有那些?

3.第一个视频里机器的“琴棋书画”令人印象深刻,未来,人工智能在这些艺术领域是否能超过或替代人类?

【第二部分】代码练习 

2.1 pytorch 基础练习

1. 定义数据

一般定义数据使用torch.Tensor , tensor的意思是张量,是数字各种形式的总称。

import torch

# 可以是一个数
x = torch.tensor(666)
print(x)

# 可以是一维数组(向量)
x = torch.tensor([1,2,3,4,5,6])
print(x)

# 可以是二维数组(矩阵)
x = torch.ones(2,3)
print(x)

# 可以是任意维度的数组(张量)
x = torch.ones(2,3,4)
print(x)

Tensor支持各种各样类型的数据,包括:

torch.float32, torch.float64, torch.float16, torch.uint8, torch.int8, torch.int16, torch.int32, torch.int64 。这里不过多描述。

创建Tensor有多种方法,包括:ones, zeros, eye, arange, linspace, rand, randn, normal, uniform, randperm, 使用的时候可以在线搜,下面主要通过代码展示。

# 创建一个空张量
x = torch.empty(5,3)
print(x)

# 创建一个随机初始化的张量
x = torch.rand(5,3)
print(x)

# 创建一个全0的张量,里面的数据类型为 long
x = torch.zeros(5,3,dtype=torch.long)
print(x)

# 基于现有的tensor,创建一个新tensor,
# 从而可以利用原有的tensor的dtype,device,size之类的属性信息
y = x.new_ones(5,3)   #tensor new_* 方法,利用原来tensor的dtype,device
print(y)

z = torch.randn_like(x, dtype=torch.float)    # 利用原来的tensor的大小,但是重新定义了dtype
print(z)

2. 定义操作

凡是用Tensor进行各种运算的,都是Function

最终,还是需要用Tensor来进行计算的,计算无非是

  • 基本运算,加减乘除,求幂求余
  • 布尔运算,大于小于,最大最小
  • 线性运算,矩阵乘法,求模,求行列式

基本运算包括: abs/sqrt/div/exp/fmod/pow ,及一些三角函数 cos/ sin/ asin/ atan2/ cosh,及 ceil/round/floor/trunc 等具体在使用的时候可以百度一下

布尔运算包括: gt/lt/ge/le/eq/ne,topk, sort, max/min

线性计算包括: trace, diag, mm/bmm,t,dot/cross,inverse,svd 等

# 创建一个 2x4 的tensor
m = torch.Tensor([[2, 5, 3, 7],
                  [4, 2, 1, 9]])

print(m.size(0), m.size(1), m.size(), sep=' -- ')

# 返回 m 中元素的数量
print(m.numel())

# 返回 第0行,第2列的数
print(m[0][2])

# 返回 第1列的全部元素
print(m[:, 1])

# 返回 第0行的全部元素
print(m[0, :])

# Create tensor of numbers from 1 to 5
# 注意这里结果是1到4,没有5
v = torch.arange(1, 5)
print(v)

# Scalar product
m @ v

注意,此处代码报错,报错信息是RuntimeError: expected scalar type Float but found Long,也就是我们的v是torch.long类型的,而m是torch.float类型,所以在做矩阵乘法的时候这两种类型的不一致导致了报错,解决方法就是把v的dtype显示地设置成torch.float,代码就可以成功运行了。

我们在上一行代码将v转换成float类型:

此时,报错解决,代码可以成功运行。

# Calculated by 1*2 + 2*5 + 3*3 + 4*7
m[[0], :] @ v

# Add a random tensor of size 2x4 to m
m + torch.rand(2, 4)

# 转置,由 2x4 变为 4x2
print(m.t())

# 使用 transpose 也可以达到相同的效果,具体使用方法可以百度
print(m.transpose(0, 1))

# returns a 1D tensor of steps equally spaced points between start=3, end=8 and steps=20
torch.linspace(3, 8, 20)

from matplotlib import pyplot as plt

# matlabplotlib 只能显示numpy类型的数据,下面展示了转换数据类型,然后显示
# 注意 randn 是生成均值为 0, 方差为 1 的随机数
# 下面是生成 1000 个随机数,并按照 100 个 bin 统计直方图
plt.hist(torch.randn(1000).numpy(), 100);

# 当数据非常非常多的时候,正态分布会体现的非常明显
plt.hist(torch.randn(10**6).numpy(), 100);

# 创建两个 1x4 的tensor
a = torch.Tensor([[1, 2, 3, 4]])
b = torch.Tensor([[5, 6, 7, 8]])

# 在 0 方向拼接 (即在 Y 方各上拼接), 会得到 2x4 的矩阵
print( torch.cat((a,b), 0))

# 在 1 方向拼接 (即在 X 方各上拼接), 会得到 1x8 的矩阵
print( torch.cat((a,b), 1))

 2.2 螺旋数据分类

下面代码是下载绘图函数到本地。(画点的过程中要用到里面的一些函数)

!wget https://raw.githubusercontent.com/Atcold/pytorch-Deep-Learning/master/res/plot_lib.py

引入基本的库,然后初始化重要参数

import random
import torch
from torch import nn, optim
import math
from IPython import display
from plot_lib import plot_data, plot_model, set_default

# 因为colab是支持GPU的,torch 将在 GPU 上运行
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
print('device: ', device)

# 初始化随机数种子。神经网络的参数都是随机初始化的,
# 不同的初始化参数往往会导致不同的结果,当得到比较好的结果时我们通常希望这个结果是可以复现的,
# 因此,在pytorch中,通过设置随机数种子也可以达到这个目的
seed = 12345
random.seed(seed)
torch.manual_seed(seed)

N = 1000  # 每类样本的数量
D = 2  # 每个样本的特征维度
C = 3  # 样本的类别
H = 100  # 神经网络里隐层单元的数量

初始化 X 和 Y。 X 可以理解为特征矩阵,Y可以理解为样本标签。 结合代码可以看到,X的为一个 NxC 行, D 列的矩阵。C 类样本,每类样本是 N个,所以是 N*C 行。每个样本的特征维度是2,所以是 2列。

在 python 中,调用 zeros 类似的函数,第一个参数是 y方向的,即矩阵的行;第二个参数是 x方向的,即矩阵的列,大家得注意下,不要搞反了。下面结合代码看看 3000个样本的特征是如何初始化的。

X = torch.zeros(N * C, D).to(device)
Y = torch.zeros(N * C, dtype=torch.long).to(device)
for c in range(C):
    index = 0
    t = torch.linspace(0, 1, N) # 在[0,1]间均匀的取10000个数,赋给t
    # 下面的代码不用理解太多,总之是根据公式计算出三类样本(可以构成螺旋形)
    # torch.randn(N) 是得到 N 个均值为0,方差为 1 的一组随机数,注意要和 rand 区分开
    inner_var = torch.linspace( (2*math.pi/C)*c, (2*math.pi/C)*(2+c), N) + torch.randn(N) * 0.2
    
    # 每个样本的(x,y)坐标都保存在 X 里
    # Y 里存储的是样本的类别,分别为 [0, 1, 2]
    for ix in range(N * c, N * (c + 1)):
        X[ix] = t[index] * torch.FloatTensor((math.sin(inner_var[index]), math.cos(inner_var[index])))
        Y[ix] = c
        index += 1

print("Shapes:")
print("X:", X.size())
print("Y:", Y.size())

# visualise the data
plot_data(X, Y)

1. 构建线性模型分类

learning_rate = 1e-3
lambda_l2 = 1e-5

# nn 包用来创建线性模型
# 每一个线性模型都包含 weight 和 bias
model = nn.Sequential(
    nn.Linear(D, H),
    nn.Linear(H, C)
)
model.to(device) # 把模型放到GPU上

# nn 包含多种不同的损失函数,这里使用的是交叉熵(cross entropy loss)损失函数
criterion = torch.nn.CrossEntropyLoss()

# 这里使用 optim 包进行随机梯度下降(stochastic gradient descent)优化
optimizer = torch.optim.SGD(model.parameters(), lr=learning_rate, weight_decay=lambda_l2)

# 开始训练
for t in range(1000):
    # 把数据输入模型,得到预测结果
    y_pred = model(X)
    # 计算损失和准确率
    loss = criterion(y_pred, Y)
    score, predicted = torch.max(y_pred, 1)
    acc = (Y == predicted).sum().float() / len(Y)
    print('[EPOCH]: %i, [LOSS]: %.6f, [ACCURACY]: %.3f' % (t, loss.item(), acc))
    display.clear_output(wait=True)

    # 反向传播前把梯度置 0 
    optimizer.zero_grad()
    # 反向传播优化 
    loss.backward()
    # 更新全部参数
    optimizer.step()

这里对上面的一些关键函数进行说明:

使用 print(y_pred.shape) 可以看到模型的预测结果,为[3000, 3]的矩阵。每个样本的预测结果为3个,保存在 y_pred 的一行里。值最大的一个,即为预测该样本属于的类别

score, predicted = torch.max(y_pred, 1) 是沿着第二个方向(即X方向)提取最大值。最大的那个值存在 score 中,所在的位置(即第几列的最大)保存在 predicted 中。下面代码把第10行的情况输出,供解释说明

此外,大家可以看到,每一次反向传播前,都要把梯度清零。

print(y_pred.shape)
print(y_pred[10, :])
print(score[10])
print(predicted[10])

# Plot trained model
print(model)
plot_model(X, Y, model)

上面使用 print(model) 把模型输出,可以看到有两层:

  • 第一层输入为 2(因为特征维度为主2),输出为 100;
  • 第二层输入为 100 (上一层的输出),输出为 3(类别数)

从上面图示可以看出,线性模型的准确率最高只能达到 50% 左右,对于这样复杂的一个数据分布,线性模型难以实现准确分类。

2. 构建两层神经网络分类

learning_rate = 1e-3
lambda_l2 = 1e-5

# 这里可以看到,和上面模型不同的是,在两层之间加入了一个 ReLU 激活函数
model = nn.Sequential(
    nn.Linear(D, H),
    nn.ReLU(),
    nn.Linear(H, C)
)
model.to(device)

# 下面的代码和之前是完全一样的,这里不过多叙述
criterion = torch.nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate, weight_decay=lambda_l2) # built-in L2

# 训练模型,和之前的代码是完全一样的
for t in range(1000):
    y_pred = model(X)
    loss = criterion(y_pred, Y)
    score, predicted = torch.max(y_pred, 1)
    acc = ((Y == predicted).sum().float() / len(Y))
    print("[EPOCH]: %i, [LOSS]: %.6f, [ACCURACY]: %.3f" % (t, loss.item(), acc))
    display.clear_output(wait=True)
    
    # zero the gradients before running the backward pass.
    optimizer.zero_grad()
    # Backward pass to compute the gradient
    loss.backward()
    # Update params
    optimizer.step()

# Plot trained model
print(model)
plot_model(X, Y, model)

大家可以看到,在两层神经网络里加入 ReLU 激活函数以后,分类的准确率得到了显著提高。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

OUC_SE_GROUP19

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值