2020-02-14

1.線性回歸矢量計算

在模型訓練或預測時骡苞,我們常常會同時處理多個數據樣本并用到矢量計算啦扬。在介紹線性回歸的矢量計算表達式之前德挣,讓我們先考慮對兩個向量相加的兩種方法臼勉。

[if !supportLists]1.?[endif]向量相加的一種方法是文兢,將這兩個向量按元素逐一做標量加法晤斩。

[if !supportLists]2.?[endif]向量相加的另一種方法是,將這兩個向量直接做矢量加法姆坚。

現在我們可以來測試了澳泵。首先將兩個向量使用for循環(huán)按元素逐一做標量加法。

import?torch

import?time

# init variable a, b as 1000 dimension vector?

n =?1000

a =?torch.ones(n)

b =?torch.ones(n)

# define a timer class to record time?

class?Timer(object):

????"""Record multiple running times."""

????def?__init__(self):

????????self.times =?[]

????????self.start()


????def?start(self):

????????# start the timer

????????self.start_time =?time.time()


????def?stop(self):

????????# stop the timer and record time into a list

????????self.times.append(time.time() -?self.start_time)

????????return?self.times[-1]


????def?avg(self):

????????# calculate the average and return

????????return?sum(self.times)/len(self.times)


????def?sum(self):

????????# return the sum of recorded time

????????return?sum(self.times)


現在我們可以來測試了兼呵。首先將兩個向量使用for循環(huán)按元素逐一做標量加法兔辅。


timer = Timer()

c = torch.zeros(n)

for i in range(n):

c[i] = a[i] + b[i]

'%.5f sec' % timer.stop()


另外是使用torch來將兩個向量直接做矢量加法:


timer.start()

d = a + b

'%.5f sec' % timer.stop()


結果很明顯,后者比前者運算速度更快。因此萍程,我們應該盡可能采用矢量計算幢妄,以提升計算效率。


線性回歸模型從零開始的實現


# import packages and modules

%matplotlib?inline

import?torch

from?IPython?import?display

from?matplotlib?import?pyplot as?plt

import?numpy?as?np

import?random

?

print(torch.__version__)

生成數據集

使用線性模型來生成數據集茫负,生成一個1000個樣本的數據集蕉鸳,下面是用來生成數據的線性關系:

price=warea?area+wage?age+b

# set input feature number

num_inputs =?2

# set example number

num_examples =?1000

?

# set true weight and bias in order to generate corresponded label

true_w =?[2, -3.4]

true_b =?4.2


features =?torch.randn(num_examples, num_inputs,

??????????????????????dtype=torch.float32)

labels =?true_w[0] *?features[:, 0] +?true_w[1] *?features[:, 1] +?true_b

labels +=?torch.tensor(np.random.normal(0, 0.01, size=labels.size()),

???????????????????????dtype=torch.float32)

使用圖像來展示生成的數據

plt.scatter(features[:, 1].numpy(), labels.numpy(), 1);

讀取數據集

def?data_iter(batch_size, features, labels):

????num_examples =?len(features)

????indices =?list(range(num_examples))

????random.shuffle(indices) ?# random read 10 samples

????for?i in?range(0, num_examples, batch_size):

????????j =?torch.LongTensor(indices[i: min(i +?batch_size, num_examples)]) # the last time may be not enough for a whole batch

????????yield??features.index_select(0, j), labels.index_select(0, j)

batch_size =?10


for?X, y in?data_iter(batch_size, features, labels):

????print(X, '\n', y)

????break

初始化模型參數

w =?torch.tensor(np.random.normal(0, 0.01, (num_inputs, 1)), dtype=torch.float32)

b =?torch.zeros(1, dtype=torch.float32)


w.requires_grad_(requires_grad=True)

b.requires_grad_(requires_grad=True)

定義模型

定義用來訓練參數的訓練模型:

price=warea?area+wage?age+b

def?linreg(X, w, b):

????return?torch.mm(X, w) +?b

定義優(yōu)化函數

在這里優(yōu)化函數使用的是小批量隨機梯度下降:

(w,b)←(w,b)?η|B|∑i∈B?(w,b)l(i)(w,b)

def?sgd(params, lr, batch_size):

????for?param in?params:

????????param.data -=?lr *?param.grad /?batch_size

# ues .data to operate param without gradient track

訓練

當數據集、模型忍法、損失函數和優(yōu)化函數定義完了之后就可來準備進行模型的訓練了潮尝。

# super parameters initlr =?0.03num_epochs =?5

net =?linregloss =?squared_loss

# trainingfor?epoch in?range(num_epochs): ?# training repeats num_epochs times

????# in each epoch, all the samples in dataset will be used once


????# X is the feature and y is the label of a batch sample

????for?X, y in?data_iter(batch_size, features, labels):

????????l =?loss(net(X, w, b), y).sum() ?

????????# calculate the gradient of batch sample loss

????????l.backward() ?

????????# using small batch random gradient descent to iter model parameters

????????sgd([w, b], lr, batch_size) ?

????????# reset parameter gradient

????????w.grad.data.zero_()

????????b.grad.data.zero_()

????train_l =?loss(net(features, w, b), labels)

????print('epoch %d, loss %f'?%?(epoch +?1, train_l.mean().item()))

w, true_w, b, true_b

線性回歸模型使用pytorch的簡潔實現

import?torch

from?torch?import?nn

import?numpy?as?np

torch.manual_seed(1)

print(torch.__version__)

torch.set_default_tensor_type('torch.FloatTensor')

生成數據集

在這里生成數據集跟從零開始的實現中是完全一樣的。

num_inputs =?2

num_examples =?1000


true_w =?[2, -3.4]

true_b =?4.2


features =?torch.tensor(np.random.normal(0, 1, (num_examples, num_inputs)), dtype=torch.float)

labels =?true_w[0] *?features[:, 0] +?true_w[1] *?features[:, 1] +?true_b

labels +=?torch.tensor(np.random.normal(0, 0.01, size=labels.size()), dtype=torch.float)

讀取數據集

import?torch.utils.data?as?Data

batch_size =?10

# combine featues and labels of dataset

dataset =?Data.TensorDataset(features, labels)

# put dataset into DataLoader

data_iter =?Data.DataLoader(

????dataset=dataset, ???????????# torch TensorDataset format

????batch_size=batch_size, ?????# mini batch size

????shuffle=True, ??????????????# whether shuffle the data or not

num_workers=2, ?????????????# read data in multithreading

)

for?X, y in?data_iter:

????print(X, '\n', y)

????break

定義模型

class?LinearNet(nn.Module):

????def?__init__(self, n_feature):

????????super(LinearNet, self).__init__() ?????# call father function to init

????????self.linear =?nn.Linear(n_feature, 1) ?# function prototype: `torch.nn.Linear(in_features, out_features, bias=True)`


????def?forward(self, x):

????????y =?self.linear(x)

????????return?y

net =?LinearNet(num_inputs)print(net)

# ways to init a multilayer network# method onenet =?nn.Sequential(

????nn.Linear(num_inputs, 1)

????# other layers can be added here

????)

# method tw

net =?nn.Sequential()net.add_module('linear', nn.Linear(num_inputs, 1))

# net.add_module ......

# method three

from?collections?import?OrderedDict

net =?nn.Sequential(OrderedDict([

??????????('linear', nn.Linear(num_inputs, 1))

??????????# ......

????????]))

print(net)

print(net[0])

初始化模型參數

In?[22]:

from?torch.nn?import?init

init.normal_(net[0].weight, mean=0.0, std=0.01)

init.constant_(net[0].bias, val=0.0) ?# or you can use `net[0].bias.data.fill_(0)` to modify it directly

In?[23]:

for?param in?net.parameters():

????print(param)

定義損失函數

In?[24]:

loss =?nn.MSELoss() ???# nn built-in squared loss function

???????????????????????# function prototype: `torch.nn.MSELoss(size_average=None, reduce=None, reduction='mean')`

定義優(yōu)化函數

In?[25]:

import?torch.optim?as?optim

optimizer =?optim.SGD(net.parameters(), lr=0.03) ??# built-in random gradient descent function

print(optimizer) ?# function prototype: `torch.optim.SGD(params, lr=, momentum=0, dampening=0, weight_decay=0, nesterov=False)`

訓練

In?[26]:

num_epochs =?3

for?epoch in?range(1, num_epochs +?1):

????for?X, y in?data_iter:

????????output =?net(X)

????????l =?loss(output, y.view(-1, 1))

????????optimizer.zero_grad() # reset gradient, equal to net.zero_grad()

????????l.backward()

????????optimizer.step()

????print('epoch %d, loss: %f'?%?(epoch, l.item()))

In?[27]:

# result comparision

dense =?net[0]

print(true_w, dense.weight.data)

print(true_b, dense.bias.data)


2.補充:【numpy庫函數】reshape用法饿序,包含-1這個參數

(原帖:https://blog.csdn.net/qq_37791134/article/details/90543879)

numpy.reshape(重塑):給數組一個新的形狀而不改變其數據

numpy.reshape(a, newshape, order=’C’)

參數

[if !supportLists]1.?[endif]a:array_like

要重新形成的數組勉失。

[if !supportLists]2.?[endif]newshape:int或tuple的整數

新的形狀應該與原始形狀兼容。如果是整數原探,則結果將是該長度的1-D數組乱凿。一個形狀維度可以是-1。在這種情況下咽弦,從數組的長度和其余維度推斷該值徒蟆。

[if !supportLists]3.?[endif]order:{'C','F'型型,'A'}可選

使用此索引順序讀取a的元素段审,并使用此索引順序將元素放置到重新形成的數組中。'C'意味著使用C樣索引順序讀取/寫入元素闹蒜,最后一個軸索引變化最快寺枉,回到第一個軸索引變化最慢。'F'意味著使用Fortran樣索引順序讀取/寫入元素绷落,第一個索引變化最快姥闪,最后一個索引變化最慢。注意砌烁,'C'和'F'選項不考慮底層數組的內存布局筐喳,而只是參考索引的順序。'A'意味著在Fortran類索引順序中讀/寫元素,如果a 是Fortran 在內存中連續(xù)的疏唾,否則為C樣順序。

注意:newshape : int or tuple of ints

大意是說函似,數組新的shape屬性應該要與原來的配套槐脏,如果等于-1的話,那么Numpy會根據剩下的維度計算出數組的另外一個newshape屬性值撇寞。?

舉例:有一個數組z顿天,它的shape屬性是(4, 4)?

z = np.array([[1, 2, 3, 4],?

[5, 6, 7, 8],?

[9, 10, 11, 12],?

[13, 14, 15, 16]])?

z.shape?

(4, 4)?

z.reshape(-1)?

array([ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16])


z.reshape(-1, 1),是說蔑担,我們不知道新z的行數是多少牌废,但是想讓z變成只有一列,行數不知的新數組啤握,通過z.reshape(-1,1)鸟缕,Numpy自動計算出有12行,新的數組shape屬性為(16, 1)排抬,與原來的(4, 4)配套懂从。z.reshape(-1,1)?

array([[ 1],?

[ 2],?

[ 3],?

[ 4],?

[ 5],?

[ 6],?

[ 7],?

[ 8],?

[ 9],?

[10],?

[11],?

[12],?

[13],?

[14],?

[15],?

[16]])


z.reshape(-1, 2),行數未知蹲蒲,列數等于2番甩,reshape后的shape等于(8, 2)?

z.reshape(-1, 2)?

array([[ 1, 2],?

[ 3, 4],?

[ 5, 6],?

[ 7, 8],?

[ 9, 10],?

[11, 12],?

[13, 14],?

[15, 16]])


同理,只給定行數届搁,列數未知缘薛,也可以設置newshape等于-1,Numpy也可以自動計算出新數組的列數卡睦。




[if !supportLists]4.?[endif]最?似然估計與最小化交叉熵損失函數

(https://blog.csdn.net/zgcr654321/article/details/85204049)

似然的概念:“似然”用通俗的話來說就是可能性宴胧,極大似然就是最大的可能性。

似然函數:似然函數是關于統計模型中的一組概率的函數(這些概率的真實值我們并不知道)么翰,似然函數的因變量值表示了模型中的概率參數的似然性(可能性)牺汤。

最大似然估計:我們列出似然函數后,從真實事件中取得一批n個采樣樣本數據浩嫌,最大似然估計會尋找基于我們的n個值的采樣數據得到的關于的最可能的概率值(即在所有可能的概率取值中檐迟,尋找一組概率值使這n個值的采樣數據的“可能性”最大化)。

最大似然估計中采樣需滿足一個很重要的假設码耐,就是所有的采樣都是獨立同分布的追迟。

伯努利分布:伯努利分布又名兩點分布或0-1分布,介紹伯努利分布前首先需要引入伯努利試驗骚腥。

伯努利試驗是只有兩種可能結果的單次隨機試驗敦间,即對于一個隨機變量X而言:

P(X=1)=p

P(X=0)=1?p

伯努利試驗可以表達為“是或否”的問題。

如果試驗E是一個伯努利試驗,將E獨立重復地進行n次廓块,則稱這一串重復的獨立試驗為n重伯努利試驗厢绝。

進行一次伯努利試驗,成功概率為p带猴,失敗概率為1-p昔汉,則稱隨機變量X服從伯努利分布。

其概率質量函數為:


伯努利分布的


伯努利分布是一個離散型機率分布拴清,是N=1時二項分布的特殊情況靶病。

伯努利分布下的最大似然估計推導出交叉熵損失函數:

假設

P(X=1)=p,P(X=0)=1?p

則有概率質量函數為


因為我們只有一組采樣數據集D,我們可以統計得到X和1-X的值口予,但p值(概率)未知娄周。下面我們要建立對數似然函數,并根據采樣數據集D求出P沪停。

對數似然函數為:


我們可以發(fā)現上式和深度學習模型中交叉熵損失函數的形式幾乎相同煤辨。這個函數的值總是小于0的,而我們要做極大似然估計就是求其極大值牙甫,也就是說掷酗,這個函數的值在深度學習的梯度下降過程中從一個負數不斷增大接近0(始終小于0)。為了與其他損失函數形式統一窟哺,我們在前面加上一個負號泻轰,這樣就和其他損失函數一樣是從一個大值不斷降低向0接近了。

深度學習模型中的交叉熵函數形式:


現在我們再用求導得極小值點的方法來求其極大似然估計且轨,首先將上式對p求導浮声,并令導數為0。

?

消去分母旋奢,得:


這就是伯努利分布下最大似然估計求出的P泳挥。

?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市至朗,隨后出現的幾起案子屉符,更是在濱河造成了極大的恐慌,老刑警劉巖锹引,帶你破解...
    沈念sama閱讀 210,978評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件矗钟,死亡現場離奇詭異,居然都是意外死亡嫌变,警方通過查閱死者的電腦和手機吨艇,發(fā)現死者居然都...
    沈念sama閱讀 89,954評論 2 384
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來腾啥,“玉大人东涡,你說我怎么就攤上這事冯吓。” “怎么了疮跑?”我有些...
    開封第一講書人閱讀 156,623評論 0 345
  • 文/不壞的土叔 我叫張陵组贺,是天一觀的道長。 經常有香客問我祖娘,道長锣披,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,324評論 1 282
  • 正文 為了忘掉前任贿条,我火速辦了婚禮,結果婚禮上增热,老公的妹妹穿的比我還像新娘整以。我一直安慰自己,他們只是感情好峻仇,可當我...
    茶點故事閱讀 65,390評論 5 384
  • 文/花漫 我一把揭開白布公黑。 她就那樣靜靜地躺著,像睡著了一般摄咆。 火紅的嫁衣襯著肌膚如雪凡蚜。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,741評論 1 289
  • 那天吭从,我揣著相機與錄音朝蜘,去河邊找鬼。 笑死涩金,一個胖子當著我的面吹牛谱醇,可吹牛的內容都是我干的。 我是一名探鬼主播步做,決...
    沈念sama閱讀 38,892評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼副渴,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了全度?” 一聲冷哼從身側響起煮剧,我...
    開封第一講書人閱讀 37,655評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎将鸵,沒想到半個月后勉盅,有當地人在樹林里發(fā)現了一具尸體,經...
    沈念sama閱讀 44,104評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡咨堤,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,451評論 2 325
  • 正文 我和宋清朗相戀三年菇篡,在試婚紗的時候發(fā)現自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片一喘。...
    茶點故事閱讀 38,569評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡驱还,死狀恐怖嗜暴,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情议蟆,我是刑警寧澤闷沥,帶...
    沈念sama閱讀 34,254評論 4 328
  • 正文 年R本政府宣布,位于F島的核電站咐容,受9級特大地震影響舆逃,放射性物質發(fā)生泄漏。R本人自食惡果不足惜戳粒,卻給世界環(huán)境...
    茶點故事閱讀 39,834評論 3 312
  • 文/蒙蒙 一路狮、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧蔚约,春花似錦奄妨、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,725評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至树枫,卻和暖如春直焙,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背砂轻。 一陣腳步聲響...
    開封第一講書人閱讀 31,950評論 1 264
  • 我被黑心中介騙來泰國打工奔誓, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人搔涝。 一個月前我還...
    沈念sama閱讀 46,260評論 2 360
  • 正文 我出身青樓丝里,卻偏偏與公主長得像,于是被迫代替她去往敵國和親体谒。 傳聞我的和親對象是個殘疾皇子杯聚,可洞房花燭夜當晚...
    茶點故事閱讀 43,446評論 2 348

推薦閱讀更多精彩內容