Task 01
線性回歸
理論部分筆記
代碼知識(shí)記錄
torch.randn():產(chǎn)生一個(gè)標(biāo)準(zhǔn)正態(tài)分布的張量
np.random.normal():高斯分布专钉,參數(shù):(均值,標(biāo)準(zhǔn)差双霍,shape)
torch.tensor():生成tensor的函數(shù)
display.set_matplotlib_formats('svg'):用來(lái)設(shè)置展示的時(shí)候使用的圖像類型描姚,這里是設(shè)置成“向量圖”的類型
plt.rcParams['figure.figsize']:用來(lái)設(shè)置展示向量圖的時(shí)候圖像的大小
plt.scatter():畫散點(diǎn)圖的函數(shù)卜录,參數(shù):(x坐標(biāo),y坐標(biāo),點(diǎn)的大小)
list(range()):創(chuàng)建一個(gè)可用于循環(huán)的整數(shù)列表,其中range()返回的是一個(gè)可迭代對(duì)象
random.shuffle():將序列的所有元素隨機(jī)排序
torch.LongTensor()是一種CPU張量捂敌,是64-bit integer(signed)的數(shù)據(jù)類型
使用了 yield 的函數(shù)被稱為生成器艾扮,生成器是一個(gè)返回迭代器的函數(shù)。
-
pytorch中張量的函數(shù)index_select(dim, index):從張量的某個(gè)維度的指定位置選取數(shù)據(jù)占婉。
參數(shù)dim:表示從第幾維挑選數(shù)據(jù)泡嘴,類型為int值
參數(shù)index:表示從第一個(gè)參數(shù)維度中的哪個(gè)位置挑選數(shù)據(jù),類型為torch.Tensor類的實(shí)例
該函數(shù)的另一種使用方法:torch.index_select(張量,dim,index)
torch.zeros(shape,dtype):生成全0張量
所有的tensor都有.requires_grad屬性逆济,用于說(shuō)明當(dāng)前量是否需要在計(jì)算中保留對(duì)應(yīng)的梯度信息酌予,默認(rèn)為False,要訓(xùn)練的參數(shù)以及它所在的梯度回傳鏈上的其它參數(shù)需要保留梯度信息奖慌,即需要將該屬性設(shè)為True抛虫。如果想改變?cè)搶傩裕驼{(diào)用tensor.requires_grad_()方法简僧。
torch.mm():矩陣相乘
torch.view(size):resize操作建椰,改變張量的size
torch.item():得到一個(gè)元素張量里面的元素值
torch.manual_seed(種子):使用種子生成隨機(jī)數(shù),種子固定的話隨機(jī)數(shù)就是固定的
torch.set_default_tensor_type(數(shù)據(jù)類型):用于改變tensor中數(shù)據(jù)的默認(rèn)類型
torch.nn.Linear(每個(gè)輸入樣本的大小岛马,每個(gè)輸出樣本的大小)
torch.nn.Sequential().一個(gè)時(shí)序容器棉姐。Modules會(huì)以他們傳入的順序被添加到容器中。當(dāng)然啦逆,也可以傳入一個(gè)OrderedDict伞矩。
init模塊的初始化函數(shù): init.normal_(參數(shù),mean,std)
init.constant_(參數(shù),值) 使用init模塊初始化參數(shù)能夠自動(dòng)給參數(shù)附加梯度(不用手動(dòng)添加了)nn.MSELoss():均方誤差損失函數(shù)
隨機(jī)梯度下降函數(shù)torch.optim.SGD(參數(shù),lr,momentum=0,...)
Softmax與分類模型
理論部分筆記
代碼知識(shí)記錄
- torchvision包是服務(wù)于PyTorch深度學(xué)習(xí)框架的夏志,主要用來(lái)構(gòu)建計(jì)算機(jī)視覺(jué)模型乃坤。torchvision主要由以下幾部分構(gòu)成:
- torchvision.datasets: 一些加載數(shù)據(jù)的函數(shù)及常用的數(shù)據(jù)集接口;
- torchvision.models: 包含常用的模型結(jié)構(gòu)(含預(yù)訓(xùn)練模型)沟蔑,例如AlexNet湿诊、VGG、ResNet等溉贿;
- torchvision.transforms: 常用的圖片變換枫吧,例如裁剪、旋轉(zhuǎn)等宇色;
- torchvision.utils: 其他的一些有用的方法。
-
class torchvision.datasets.FashionMNIST(root, train=True, transform=None, target_transform=None, download=False)
root(string)– 數(shù)據(jù)集的根目錄,其中存放processed/training.pt和processed/test.pt文件宣蠕。
train(bool, 可選)– 如果設(shè)置為True例隆,從training.pt創(chuàng)建數(shù)據(jù)集,否則從test.pt創(chuàng)建抢蚀。
download(bool, 可選)– 如果設(shè)置為True镀层,從互聯(lián)網(wǎng)下載數(shù)據(jù)并放到root文件夾下。如果root目錄下已經(jīng)存在數(shù)據(jù)皿曲,不會(huì)再次下載唱逢。
transform(可被調(diào)用 , 可選)– 一種函數(shù)或變換,輸入PIL圖片屋休,返回變換之后的數(shù)據(jù)坞古。如:transforms.RandomCrop。
target_transform(可被調(diào)用 , 可選)– 一種函數(shù)或變換劫樟,輸入目標(biāo)痪枫,進(jìn)行變換。
-
對(duì)多維Tensor按維度求和:
X = torch.tensor([[1, 2, 3], [4, 5, 6]]) print(X.sum(dim=0, keepdim=True)) # dim為0叠艳,按照相同的列求和奶陈,并在結(jié)果中保留列特征 print(X.sum(dim=1, keepdim=True)) # dim為1,按照相同的行求和附较,并在結(jié)果中保留行特征 print(X.sum(dim=0, keepdim=False)) # dim為0吃粒,按照相同的列求和,不在結(jié)果中保留列特征 print(X.sum(dim=1, keepdim=False)) # dim為1拒课,按照相同的行求和徐勃,不在結(jié)果中保留行特征
運(yùn)行結(jié)果:
tensor([[5, 7, 9]])
tensor([[ 6],
? [15]])
tensor([5, 7, 9])
tensor([ 6, 15]) #雖然按行求和,但沒(méi)保留行特征
-
math.exp()
:返回x的指數(shù)ex
-
numpy的廣播機(jī)制:numpy中兩個(gè)數(shù)組的加減乘除都是對(duì)應(yīng)元素之間的操作捕发,而當(dāng)兩個(gè)數(shù)組的形狀并不相同時(shí)疏旨,比如其中一個(gè)shape是(1,),那么會(huì)自動(dòng)將該數(shù)組的形狀擴(kuò)展至匹配與它做運(yùn)算的數(shù)組
例:
A = numpy.array([1,2,3]) result = A + 100 print(result)
能得到結(jié)果[101 102 103],不需要自己去寫A + [100, 100, 100]了扎酷。
-
torch.gather(input, dim, index, out=None)
: 沿給定軸dim檐涝,將輸入索引張量index指定位置的值取出并進(jìn)行進(jìn)行聚合。或
input.gather(dim, index, ...)
例:
y_hat = torch.tensor([[0.1, 0.3, 0.6], [0.3, 0.2, 0.5]]) y = torch.LongTensor([0, 2]) y_hat.gather(1, y.view(-1, 1)) #也就是y_hat.gather(1, torch.LongTensor([[0], [2]]))
dim=1法挨,按行取谁榜。index為[[0], [2]],也就是說(shuō)第0行取第0列的凡纳,第1行取第2列的
結(jié)果:
tensor([[0.1000],
[0.5000]]) torch.log()
:求自然對(duì)數(shù)torch.argmax(input, dim=None, keepdim=False)
:返回指定維度最大值的序號(hào)torch.nn.CrossEntropyLoss(weight=None, size_average=None, ignore_index=-100, reduce=None, reduction='mean')
:求交叉熵torch.optim.SGD(params, lr=, momentum=0, dampening=0, weight_decay=0, nesterov=False)
:定義SGD優(yōu)化器
多層感知機(jī)
代碼知識(shí)記錄
torch.arange(start=0, end, step=1,..., requires_grad=False)
:生成一個(gè)從start到end(不包含)窃植,步長(zhǎng)為step的tensorx.relu():求tensor x的ReLU函數(shù)值:
x.sigmoid():求tensor x的Sigmoid函數(shù)值:
-
x.tanh():求tensor x的雙曲正切函數(shù)值:
-
標(biāo)量f對(duì)矩陣X的導(dǎo)數(shù),定義為:
即f對(duì)X逐元素求導(dǎo)排成與X尺寸相同的矩陣荐糜。(矩陣和向量的求導(dǎo)法則:https://blog.csdn.net/jmh1996/article/details/85040660)
-
關(guān)于torch.backward()矩陣的說(shuō)明:
設(shè)x是一個(gè)tensor巷怜,y是關(guān)于x的函數(shù)y(x)葛超。
backward()默認(rèn)是標(biāo)量對(duì)某個(gè)量(標(biāo)量、向量延塑、矩陣)的求導(dǎo)绣张。
如果y本身就是標(biāo)量,那么若x的requires_grad屬性設(shè)置為True关带,則y.backward()表示侥涵。這時(shí)候backward()函數(shù)中不用加參數(shù)。
如果y是向量或者矩陣宋雏,那么y.backward()表示的是將y先進(jìn)行所有元素的“加權(quán)求和”轉(zhuǎn)換成一個(gè)標(biāo)量芜飘,再用這個(gè)標(biāo)量對(duì)x求導(dǎo)。這時(shí)候就必須要在backward()函數(shù)中加入一個(gè)tensor類型的參數(shù)磨总,而且這個(gè)參數(shù)的size必須和y的size一致嗦明,這個(gè)參數(shù)表示的是對(duì)y的各個(gè)元素進(jìn)行“加權(quán)求和”時(shí)各個(gè)元素對(duì)應(yīng)的權(quán)重。
另外要注意backward()會(huì)自動(dòng)累加所求的梯度舍败,所以有需要的時(shí)候要進(jìn)行梯度清零操作x.grad.zero_()或者optimizer.zero_grad()
-
關(guān)于激活函數(shù)的選擇:
ReLu函數(shù)是一個(gè)通用的激活函數(shù)招狸,目前在大多數(shù)情況下使用。但是邻薯,ReLU函數(shù)只能在隱藏層中使用裙戏。
用于分類器時(shí),sigmoid函數(shù)及其組合通常效果更好厕诡。由于梯度消失問(wèn)題累榜,有時(shí)要避免使用sigmoid和tanh函數(shù)。
在神經(jīng)網(wǎng)絡(luò)層數(shù)較多的時(shí)候灵嫌,最好使用ReLu函數(shù)壹罚,ReLu函數(shù)比較簡(jiǎn)單計(jì)算量少,而sigmoid和tanh函數(shù)計(jì)算量大很多寿羞。
在選擇激活函數(shù)的時(shí)候可以先選用ReLu函數(shù)如果效果不理想可以嘗試其他激活函數(shù)猖凛。
- 多層感知機(jī)就是含有至少一個(gè)隱藏層的由全連接層組成的神經(jīng)網(wǎng)絡(luò),且每個(gè)隱藏層的輸出通過(guò)激活函數(shù)進(jìn)行變換绪穆。多層感知機(jī)的層數(shù)和各隱藏層中隱藏單元個(gè)數(shù)都是超參數(shù)辨泳。
-
torch.max()
:torch.max(input):選出input中最大的元素
torch.max(input, dim, keepdim=False, out=None)
torch.max(input, other, out=None):將input和other做逐元素的比較,每個(gè)元素都返回較大的那個(gè)值玖院。
Task 02
文本預(yù)處理
代碼知識(shí)記錄
-
文本數(shù)據(jù)的常見(jiàn)預(yù)處理步驟:
- 讀入文本
- 分詞
- 建立字典菠红,將每個(gè)詞映射到一個(gè)唯一的索引(index)
- 將文本從詞的序列轉(zhuǎn)換為索引的序列,方便輸入模型
-
with語(yǔ)句打開(kāi)文件:
with open(文件路徑, 打開(kāi)方式) as f:
-
每次讀入文件一行的方法:
法1:
while True: line = f.readline() if line: pass # do something here else: break
法2:
for line in f: pass # do something here
- 讀入整個(gè)文件:f.read()
-
re.sub(pattern, repl, string, count=0, flags=0)
:通過(guò)正則表達(dá)式實(shí)現(xiàn)替換字符串中的匹配項(xiàng)(簡(jiǎn)單的替換功能可以用普通字符串的replace()函數(shù)實(shí)現(xiàn))pattern:表示正則表達(dá)式中的模式字符串难菌;
repl:被替換的字符串(既可以是字符串试溯,也可以是函數(shù))
string:: 要被查找替換的原始字符串
count:模式匹配后替換的最大次數(shù),默認(rèn) 0 表示替換所有的匹配
flags:編譯時(shí)用的匹配模式郊酒,數(shù)字形式
正則表達(dá)式模式:
- ^:匹配字符串的開(kāi)頭
- $:匹配字符串的末尾
- [...]:用來(lái)表示一組字符遇绞,單獨(dú)列出:[amk]匹配'a','m'或'k'
- [^...]:不在[]中的字符:[ ^abc]:匹配除了a,b,c之外的字符
- re+:匹配1個(gè)或多個(gè)的表達(dá)式键袱。
- [a-z]:匹配任何小寫字母
- [0-9]:匹配任何數(shù)字
例:
line = "asq3w7452e1"
print(re.sub('[^a-z]+','*',line))
#輸出為:asq*w*e*
(更多正則表達(dá)式模式詳見(jiàn)https://www.runoob.com/python3/python3-reg-expressions.html)
-
str.split(str="", num=string.count(str))
: 通過(guò)指定分隔符對(duì)字符串進(jìn)行切片,如果參數(shù) num 有指定值试读,則分隔 num+1 個(gè)子字符串杠纵。分隔符默認(rèn)為所有的空字符荠耽,包括空格钩骇、換行(\n)、制表符(\t)等铝量。
- collections.Counter(列表或者字符串等):可返回對(duì)象的Counter字典倘屹,其中<key, value>: <列表中的元素,元素出現(xiàn)的頻率>
-
enumerate(sequence, [start=0])
:用于將一個(gè)可遍歷的數(shù)據(jù)對(duì)象(如列表慢叨、元組或字符串)組合為一個(gè)索引序列纽匙,同時(shí)列出數(shù)據(jù)和數(shù)據(jù)下標(biāo),一般用在 for 循環(huán)當(dāng)中拍谐。
-
isinstance(object, classinfo)
:判斷一個(gè)對(duì)象是否是一個(gè)已知的類型烛缔,類似 type()。它與type()的區(qū)別:
- type() 不會(huì)認(rèn)為子類是一種父類類型轩拨,不考慮繼承關(guān)系践瓷。
- isinstance() 會(huì)認(rèn)為子類是一種父類類型,考慮繼承關(guān)系亡蓉。
-
有一些現(xiàn)有的工具可以很好地進(jìn)行分詞晕翠,例如:spaCy和NLTK
用法:
text = "Mr. Chen doesn't agree with my suggestion." #spaCy: import spacy nlp = spacy.load('en_core_web_sm') doc = nlp(text) print([token.text for token in doc]) #NLTK: from nltk.tokenize import word_tokenize from nltk import data data.path.append('/home/kesci/input/nltk_data3784/nltk_data') print(word_tokenize(text)) #輸出結(jié)果均為:['Mr.', 'Chen', 'does', "n't", 'agree', 'with', 'my', 'suggestion', '.']
語(yǔ)言模型
理論部分筆記
代碼知識(shí)記錄
- 集合(set)是一個(gè)無(wú)序的不重復(fù)元素序列】潮簦可以使用大括號(hào) { } 或者 set() 函數(shù)創(chuàng)建集合淋肾,注意:創(chuàng)建一個(gè)空集合必須用 set()。
時(shí)序數(shù)據(jù)的采樣
假設(shè)語(yǔ)言數(shù)據(jù)集為:
想要有直升機(jī)爸邢,想要和你飛到宇宙去樊卓。想要和你融化在一起,融化在宇宙里……
在訓(xùn)練中我們需要每次隨機(jī)讀取小批量樣本和標(biāo)簽杠河。與之前章節(jié)的實(shí)驗(yàn)數(shù)據(jù)不同的是碌尔,時(shí)序數(shù)據(jù)的一個(gè)樣本通常包含連續(xù)的字符。假設(shè)時(shí)間步數(shù)為5感猛,樣本序列為5個(gè)字符七扰,即“想”“要”“有”“直”“升”。該樣本的標(biāo)簽序列為這些字符分別在訓(xùn)練集中的下一個(gè)字符陪白,即“要”“有”“直”“升”“機(jī)”颈走,即=“想要有直升”,=“要有直升機(jī)”咱士。
現(xiàn)在我們考慮序列“想要有直升機(jī)立由,想要和你飛到宇宙去”轧钓,如果時(shí)間步數(shù)為5,有以下可能的樣本和標(biāo)簽:
- :“想要有直升”锐膜,:“要有直升機(jī)”
- :“要有直升機(jī)”毕箍,:“有直升機(jī),”
- :“有直升機(jī)道盏,”而柑,:“直升機(jī),想”
- ...
- :“要和你飛到”荷逞,:“和你飛到宇”
- :“和你飛到宇”媒咳,:“你飛到宇宙”
- :“你飛到宇宙”,:“飛到宇宙去”
可以看到种远,如果序列的長(zhǎng)度為涩澡,時(shí)間步數(shù)為,那么一共有個(gè)合法的樣本坠敷,但是這些樣本有大量的重合妙同,我們通常采用更加高效的采樣方式。我們有兩種方式對(duì)時(shí)序數(shù)據(jù)進(jìn)行采樣膝迎,分別是隨機(jī)采樣和相鄰采樣粥帚。
隨機(jī)采樣
設(shè)批量大小batch_size
是每個(gè)小批量的樣本數(shù),num_steps
是每個(gè)樣本所包含的時(shí)間步數(shù)弄抬。
過(guò)程:將語(yǔ)料庫(kù)的字符數(shù)減1整除時(shí)間步數(shù)茎辐,得到的就是樣本數(shù)量。將樣本之間的順序打亂掂恕,然后每個(gè)batch取batch_size個(gè)樣本拖陆。
代碼:
import torch
import random
def data_iter_random(corpus_indices, batch_size, num_steps, device=None):
#corpus_indices是語(yǔ)料庫(kù)的字符數(shù),device用來(lái)控制最后返回的批量要放到什么設(shè)備上
# 減1是因?yàn)閷?duì)于長(zhǎng)度為n的序列懊亡,X最多只有包含其中的前n - 1個(gè)字符
num_examples = (len(corpus_indices) - 1) // num_steps # 下取整依啰,得到不重疊情況下的樣本個(gè)數(shù)
example_indices = [i * num_steps for i in range(num_examples)] # 每個(gè)樣本的第一個(gè)字符在corpus_indices中的下標(biāo)
random.shuffle(example_indices)
def _data(i):
# 返回從i開(kāi)始的長(zhǎng)為num_steps的序列
return corpus_indices[i: i + num_steps]
if device is None:
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
for i in range(0, num_examples, batch_size):
# 每次選出batch_size個(gè)隨機(jī)樣本
batch_indices = example_indices[i: i + batch_size] # 當(dāng)前batch的各個(gè)樣本的首字符的下標(biāo)
X = [_data(j) for j in batch_indices]
Y = [_data(j + 1) for j in batch_indices]
yield torch.tensor(X, device=device), torch.tensor(Y, device=device)
相鄰采樣
相鄰的兩個(gè)隨機(jī)小批量在原始序列上的位置相毗鄰。
代碼:
def data_iter_consecutive(corpus_indices, batch_size, num_steps, device=None):
if device is None:
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
corpus_len = len(corpus_indices) // batch_size * batch_size # 保留下來(lái)的序列的長(zhǎng)度
corpus_indices = corpus_indices[: corpus_len] # 僅保留前corpus_len個(gè)字符
indices = torch.tensor(corpus_indices, device=device)
indices = indices.view(batch_size, -1) # resize成(batch_size, )
batch_num = (indices.shape[1] - 1) // num_steps
for i in range(batch_num):
i = i * num_steps
X = indices[:, i: i + num_steps]
Y = indices[:, i + 1: i + num_steps + 1]
yield X, Y
循環(huán)神經(jīng)網(wǎng)絡(luò)基礎(chǔ)
理論知識(shí)筆記
代碼知識(shí)記錄
-
scatter_(input, dim, index, src) → Tensor
將src中的所有值按照index確定的索引寫入本tensor中店枣。其中索引是根據(jù)給定的dimension速警,dim按照
gather()
描述的規(guī)則來(lái)確定。注意鸯两,index的值必須是在0到(self.size(dim)-1)之間闷旧,
參數(shù):input (Tensor)-源tensor;dim (int)-索引的軸向钧唐;index (LongTensor)-散射元素的索引指數(shù)忙灼;src (Tensor or float)-散射的源元素
例:
>>> x = torch.rand(2, 5) >>> x 0.4319 0.6500 0.4080 0.8760 0.2355 0.2609 0.4711 0.8486 0.8573 0.1029 [torch.FloatTensor of size 2x5] >>> torch.zeros(3, 5).scatter_(0, torch.LongTensor([[0, 1, 2, 0, 0], [2, 0, 0, 1, 2]]), x) 0.4319 0.4711 0.8486 0.8760 0.2355 0.0000 0.6500 0.0000 0.8573 0.0000 0.2609 0.0000 0.4080 0.0000 0.1029 [torch.FloatTensor of size 3x5] >>> z = torch.zeros(2, 4).scatter_(1, torch.LongTensor([[2], [3]]), 1.23) >>> z 0.0000 0.0000 1.2300 0.0000 0.0000 0.0000 0.0000 1.2300 [torch.FloatTensor of size 2x4]
torch.detach()
:將一個(gè)變量從創(chuàng)建它的計(jì)算圖中分離,并把它設(shè)置成葉子結(jié)點(diǎn)變量。-
如果模型采用隨機(jī)采樣该园,那么在每個(gè)小批量更新前初始化隱藏狀態(tài)酸舍。
如果模型采用相鄰采樣,那么在每個(gè)epoch開(kāi)始時(shí)初始化隱藏狀態(tài)即可里初。但是在每個(gè)小批量更新前啃勉,需要使用detach函數(shù)從計(jì)算圖分離隱藏狀態(tài)。
原因:在訓(xùn)練過(guò)程中双妨,同個(gè)epoch隨著batch的增大淮阐,模型的損失函數(shù)關(guān)于隱層變量的梯度傳播的更遠(yuǎn),計(jì)算開(kāi)銷也更大斥难。為減小計(jì)算開(kāi)銷枝嘶,一般在每個(gè)batch開(kāi)始的時(shí)候把隱層狀態(tài)從計(jì)算圖中分離出來(lái)。 torch.cat(inputs, dimension=0) → Tensor
:在給定維度上對(duì)輸入的張量序列進(jìn)行連接操作哑诊。-
class torch.nn.RNN
之中的幾個(gè)構(gòu)造函數(shù)參數(shù):- input_size - 輸入x的特征數(shù)量。
- hidden_size – 隱層的特征數(shù)量及刻。
- num_layers – RNN的層數(shù)镀裤。
- nonlinearity – 指定非線性激活函數(shù)使用tanh還是relu。默認(rèn)是tanh缴饭。
- batch_first – 如果True的話暑劝,那么輸入Tensor的shape應(yīng)該是[batch_size, time_step, feature],輸出也是這樣。默認(rèn)是False颗搂。
使用默認(rèn)的參數(shù)False對(duì)應(yīng)的輸入形狀是 (num_steps, batch_size, input_size)担猛。
torch.stack(sequence, dim=0)
:沿著一個(gè)新維度對(duì)輸入張量序列進(jìn)行連接。 序列中所有的張量都應(yīng)該為相同形狀丢氢。