本篇博客记录学习《动手学深度学习》课程过程中的一些笔记。第一次打卡,包括Task1和Task2。
Task01
线性回归
torch.Tensor
是一种包含单一数据类型元素的多维矩阵
torch.index_select(input, dim, index, out=None)
- input(Tensor) - 输入张量
- dim(int) - 索引的轴
- index(LongTensor) - 包含索引下标的一维张量
- out - 目标张量
requires_grad
-是否为自动求导记录相关的运算,默认值为False
w.requires_grad_(requires_grad=True)
b.requires_grad_(requires_grad=True)
PyTorch广播机制:
if a PyTorch operation supports broadcast, then its Tensor arguments can be automatically expanded to be of equal sizes
即,如果PyTorch操作符支持广播机制,当tensor的维度不一样,也可以自动扩展
torch.Tensor与torch.tensor的区别:
torch.Tensor()
是Python类,是默认张量类型torch.FloatTensor()
的别名
torch.tensor()
仅仅是Python的函数,原型是:
torch.tensor(data, dtype=None, device=None, requires_grad=False)
Softmax与分类模型
softmax回归是一个单层神经网络:输入层、输出层
输出层直接输出存在问题:
- 一方面,输出层的输出值范围不确定,难以直观上判断这些值的意义
- 另一方面,由于真实标签是离散值,这些离散值与不确定范围的输出值之间的误差难以衡量
所以softmax运算符将输出值变换成值为正且和为1的概率分布,返回概率最大值对应的
多层感知机
结构:输入层、隐藏层、输出层;隐藏层也是一个线性层
全连接层叠加存在的问题:
全连接层只是对数据做仿射变换,而多个仿射变换的叠加仍然是一个仿射变换,所以包含隐藏层的多层神经网络也只是与单层神经网络等价
**解决办法:**引入非线性变换,即激活函数,对隐藏变量使用按元素运算的非线性函数进行变换,然后再作为下一个全连接层的输入
ReLU函数:
R e L U ( x ) = m a x ( x , 0 ) ReLU(x) = max(x,0) ReLU(x)=max(x,0), ReLU函数只保留正数元素,并将负数元清零
Sigmoid函数:
s i g m o i d ( x ) = 1 1 + e x p ( − x ) sigmoid(x) = \frac{1}{1+exp(-x)} sigmoid(x)=1+exp(−x)1
tanh函数:
tanh(双曲正切)函数可以将元素的值变换到-1到1之间: t a n h ( x ) = 1 − e x p ( − 2 x ) 1 + e x p ( − 2 x ) tanh(x) = \frac{1-exp(-2x)}{1+exp(-2x)} tanh(x)=1+exp(−2x)1−exp(−2x)
关于激活函数的选择:
ReLU函数是一个通用的激活函数,在大多数情况下使用,但是只能在隐藏层中使用;
用于分类器时,sigmoid函数及其组合通常效果更好,由于梯度消失问题,有时要避免使用sigmoid和tanh函数;
在神经网络层数较多的时候,最好使用ReLU函数,因为其简单计算量少,而sigmoid和tanh函数计算量大很多;
在选择激活函数的时候可以先选用ReLU函数,如果效果不理想再尝试其他激活函数。
Task02
文本预处理
文本是一类序列数据,常见预处理步骤:
- 读入文本
- 分词
- 建立字典,将每个词映射到一个唯一的索引
- 将文本从词的序列转换为索引的序列,方便输入模型
正则表达式:
re.sub()
:正则表达式的替换函数
[^a-z]
:非a到z的字符
[^a-z]+
:由非a到z小写字符构成的非空字符串
re.sub('[^a-z]+',' ', line.strip().lower())
:将line去除前后空格,大写字母转换成小写,然后将由非a到z小写字符构成的非空字符串替换为空格
简单分词: 从单词序列 ——> 索引序列
现有分词工具:
-
spaCy
import spacy text = "Mr. Chen doesn't agree with my suggestion." nlp = spacy.load('en') doc = nlp(text) print([token.text for token in doc])
-
NLTK
from nltk.tokenize import word_tokenize text = "Mr. Chen doesn't agree with my suggestion." print(word_tokenize(text))
语言模型
一段自然语言文本可以看作是一个离散时间序列,给定一个长度为 T T T的词的序列 w 1 , w 2 , . . . , w T w_1,w_2,...,w_T w1,w2,...,wT,语言模型的目标是评估该序列是否合理,即计算该序列的概率: P ( w 1 , w 2 , . . . , w T ) P(w_1,w_2,...,w_T) P(w1,w2,...,wT),概率大即合理,反之则不合理
基于 n n n元语法( n n n-gram):
随着序列长度增加,计算和存储多个词共同出现的概率的复杂度会呈指数级增加,因此通过马尔科夫假设简化模型。
马尔科夫假设是指一个词的出现只与前面 n n n个词相关,即 n n n阶马尔科夫链。
n n n元语法缺陷:
- 参数空间过大
- 数据稀疏 —— 频率高的主要是停止词,如and等,计算出来的大部分参数都是0
时序数据的采样:
随机采样
相邻采样
循环神经网络
目的:基于当前的输入与过去的输入序列,预测序列的下一个字符
循环神经网络引入一个隐藏变量,用
H
t
H_t
Ht表示
H
H
H在时间步
t
t
t的值。
H
t
H_t
Ht的计算基于
X
t
X_t
Xt和
H
t
−
1
H_{t-1}
Ht−1,可以认为
H
t
H_t
Ht记录了到当前字符为止的序列信息,利用
H
t
H_t
Ht对序列的下一个字符进行预测
错题记录: