久久国内精品视频,激情懂色av一区av二区av,国产精品无码永久免费888,欧美日韩国产精品自在自线

頻道 > 生活 >   >  正文

深度學習之PyTorch實戰(5)——對CrossEntropyLoss損失函數的理解與學習 今日熱議

評論

其實這個筆記起源于一個報錯,報錯內容也很簡單,希望傳入一個三維的tensor,但是得到了一個四維。

RuntimeError: only batches of spatial targets supported (3D tensors) but got targets of dimension: 4

查看代碼報錯點,是出現在pytorch計算交叉熵損失的代碼。其實在自己手寫寫語義分割的代碼之前,我一直以為自己是對交叉熵損失完全了解的。但是實際上還是有一些些認識不足,所以這里打算復習一下,將其重新梳理一下,才算是透徹的理解了,特地記錄下來。

1,交叉熵損失的定義理解

交叉熵是信息論中的一個概念,要想完全理解交叉熵的本質,需要從基礎的概念學習。


(資料圖)

1.1 信息量

信息量與事件發生的概率有關,某件事情越不可能發生,我們獲取的信息量就越大,越可能發生,我們獲取的信息量就越小。

假設X是一個離散型隨機變量,其取值集合為x,概率分布函數 p(x)=Pr(X=x),則定義事件 X=x0的信息量為:

由于是概率,所以P(x0)的取值范圍是[0, 1],繪圖如下:

從圖像可知,函數符合我們對信息量的直覺,概率越大,信息量越小。

1.2 熵

對于某個事件來說,有多種可能性,每一種可能性都有一個概率 p(Xi),這樣就可能計算出某一種可能性的信息量。因為我們上面定義了信息量的定義,而熵就是表達所有信息量的期望,即:

而有一類比較特殊的分布問題,就是0-1分布,對于這類問題你,熵的計算方式可以簡化為圖下算式:

1.3 相對熵(KL散度)

如果我們對同一個隨機變量X有兩個單獨的概率分布 P(x) 和 Q(x)(在機器學習中,P往往是用來表示樣本的真實分布,而Q是表示模型預測的分布。),我們可以使用KL散度來衡量這兩個分布的差異。計算公式如下:

n 為事件的所有可能性,Dkl的值越小,表示P和Q的分布越接近。

1.4 交叉熵

對上式變形可以得到:

等式的前一部分是p的熵,后一部分是交叉熵:

在機器學習中,我們需要評估label和predict之間的差距,使用KL散度剛剛好。由于KL散度的前一部分 -H(y)不變,故在優化過程中,只需要關注交叉熵就可以了,所以一般在機器學習中直接用交叉熵做loss,評估模型。因為交叉熵刻畫的是兩個概率分布的距離,也就是說交叉熵值越?。ㄏ鄬氐闹翟叫。?,兩個概率分布越接近。

1.5 交叉熵在單標簽分類問題的使用

這里的單標簽分類,就是深度學習最基本的分類問題,每個圖像只有一個標簽,只能是label1或者label2。

上圖是一個樣本loss的計算方式,n代表n種label,yi表示真實結果, yihat表示預測概率。如果是一個batch,則需要除以m(m為當前batch的樣本數)。

1.6 交叉熵在多標簽分類問題的使用

這里的多標簽分類是指,每一張圖像樣本可以有多個類別,多分類標簽是n-hot,值得注意的是,這里的pred不再用softmax計算了,采用的是Sigmoid了。將每一個節點的輸出歸一化到0-1之間。所以pred的值的和也不再是1。比如我們的語義分割,每個像素的label都是獨立分布的,相互之間沒有任何影響,所以交叉熵在這里是單獨對每一個節點進行計算,每一個節點只有兩種可能性,所以是一個二項分布。(上面有簡化后交叉熵的公式)

每個樣本的loss即為 loss = loss1 + loss2 + ... lossn。

每一個batch的loss就是:

其中m為當前batch的樣本量,n為類別數。

2,Pytorch中CrossEntropy的形式

語義分割的本質是對像素的分類。因此語義分割也是使用這個損失函數。首先看代碼定義:

def cross_entropy(input, target, weight=None, size_average=None, ignore_index=-100,                  reduce=None, reduction="mean"):    # type: (Tensor, Tensor, Optional[Tensor], Optional[bool], int, Optional[bool], str) -> Tensor    if size_average is not None or reduce is not None:        reduction = _Reduction.legacy_get_string(size_average, reduce)    return nll_loss(log_softmax(input, 1), target, weight, None, ignore_index, None, reduction)

從上面代碼可知:input和target是Tensor格式,并且先計算log_softmax,再計算nll_loss。(實際上softmax計算+ log計算 + nll_loss 計算== 直接使用CrossEntropyLoss計算)

2.1 通過softmax+log+nll_loss 計算CrossEntropyLoss

我們直接在語義分割中應用:

下面softmax函數肯定輸出的是網絡的輸出預測圖像,假設維度為(1,2,2,2),從左到右dim依次為0,1,2,3,也就是說類別數所在的維度表示dim=1應在的維度上計算概率。所以dim=1

temp1 = F.softmax(pred_output,dim=1)print("temp1:",temp1)

log函數:就是對輸入矩陣的每個元素求對數,默認底數為e,也就是In函數

temp3 = torch.log(temp1)print("temp3:",temp3)

nll_loss函數:這個函數的目的是把標簽圖像的元素值,作為索引值,在上面選擇相應的值求平均。

target = target.long()loss1 = F.nll_loss(temp3,target)print("loss1: ", loss1)
2.2 直接使用交叉熵損失計算

直接使用交叉熵損失計算:

loss2 = nn.CrossEntropyLoss()result2 = loss2(pred_output, target)print("result2: ", result2)

對比結果可以發現 通過 對CrossEntropyLoss函數分解并分步計算的結果,與直接使用CrossEntropyLoss函數計算的結果一致。

2.3 pytorch 和 tensorflow在損失函數計算方面的差異

pytorch和tensorflow在損失函數計算方面有細微的差別的,為啥對比pytorch和tensorflow的差異,因為一個更符合人的想法,一個稍微有一些閹割的問題,導致我們按照常理寫代碼,會遇到問題。

tensorflow的模型訓練:

one-hot編碼:

通過這兩步驟,我們就可以計算標簽和模型產生的預測結果之間的損失了。而在pytorch中,我們不需要對標簽進行one-hot編碼,且需要將通道這一維度壓縮。即標簽中的值為對應的類別數。

具體在代碼中,如果是一個類別,就特別要注意(因為我就是沒注意,所以就有開頭的錯):

masks_pred = model(images)if model.n_classes == 1:    loss = criterion(masks_pred.squeeze(1), true_masks.float())    loss += dice_loss(F.sigmoid(masks_pred.squeeze(1)), true_masks.float(), multiclass=False)else:    loss = criterion(masks_pred, true_masks)    loss += dice_loss(        F.softmax(masks_pred, dim=1).float(),        F.one_hot(true_masks, model.n_classes).permute(0, 3, 1, 2).float(),        multiclass=True    )
3,Pytorch中,nn與nn.functional的相同點和不同點3.1 相同點

首先兩者的功能相同,nn.xx與nn.functional.xx的實際功能是相同的,只是一個是包裝好的類,一個是可以直接調用的函數。

比如我們這里學習的Crossentropy函數:

在torch.nn中定義如下:

class CrossEntropyLoss(_WeightedLoss):    __constants__ = ["ignore_index", "reduction", "label_smoothing"]    ignore_index: int    label_smoothing: float    def __init__(self, weight: Optional[Tensor] = None, size_average=None, ignore_index: int = -100,                 reduce=None, reduction: str = "mean", label_smoothing: float = 0.0) -> None:        super(CrossEntropyLoss, self).__init__(weight, size_average, reduce, reduction)        self.ignore_index = ignore_index        self.label_smoothing = label_smoothing    def forward(self, input: Tensor, target: Tensor) -> Tensor:        return F.cross_entropy(input, target, weight=self.weight,                               ignore_index=self.ignore_index, reduction=self.reduction,                               label_smoothing=self.label_smoothing)

在torch.nn.functional中定義如下:

def cross_entropy(    input: Tensor,    target: Tensor,    weight: Optional[Tensor] = None,    size_average: Optional[bool] = None,    ignore_index: int = -100,    reduce: Optional[bool] = None,    reduction: str = "mean",    label_smoothing: float = 0.0,) -> Tensor:    if has_torch_function_variadic(input, target, weight):        return handle_torch_function(            cross_entropy,            (input, target, weight),            input,            target,            weight=weight,            size_average=size_average,            ignore_index=ignore_index,            reduce=reduce,            reduction=reduction,            label_smoothing=label_smoothing,        )    if size_average is not None or reduce is not None:        reduction = _Reduction.legacy_get_string(size_average, reduce)    return torch._C._nn.cross_entropy_loss(input, target, weight, _Reduction.get_enum(reduction), ignore_index, label_smoothing)

可以看到torch.nn下面的CrossEntropyLoss類在forward時調用了nn.functional下的cross_entropy函數,當然最終的計算是通過C++編寫的函數計算的。

3.2 不同點

不同點1:在使用nn.CrossEntropyLoss()之前,需要先實例化,再輸入參數,以函數調用的方式調用實例化的對象并傳入輸入數據:

import torch.nn as nnloss = torch.nn.CrossEntropyLoss()output = loss(x, y)

使用 F.cross_entropy()直接可以傳入參數和輸入數據,而且由于F.cross_entropy() 得到的是一個向量也就是對batch中每一個圖像都會得到對應的交叉熵,所以計算出之后,會使用一個mean()函數,計算其總的交叉熵,再對其進行優化。

import torch.nn.functional as Floss = F.cross_entropy(input, target).mean()

不同點2:而且 nn.xxx 繼承于nn.Module,能夠很好的與nn.Sequential結合使用,而nn.functional.xxx 無法與nn.Sequential結合使用。舉個例子:

layer = nn.Sequential(            nn.Conv2d(3, 64, kernel_size=3, padding=1),            nn.BatchNorm2d(num_features=64),            nn.ReLU(),            nn.MaxPool2d(kernel_size=2),            nn.Dropout(0.2)  )

不同點3:nn.xxx 不需要自己定義和管理weight;而nn.functional.xxx需要自己定義weight,每次調用的時候都需要手動傳入weight,不利于代碼復用。其實如果我們只保留了nn.functional下的函數的話,在訓練或者使用時,我們就需要手動去維護weight, bias, stride 這些中間量的值;而如果只保留nn下的類的話,其實就犧牲了一部分靈活性,因為做一些簡單的計算都需要創建一個類,這也與PyTorch的風格不符。

比如使用nn.xxx定義一個網絡,如下:

import torchimport torch.nn as nnimport torch.nn.functional as Fclass Net(nn.Module):    def __init__(self):        super(Net, self).__init__()        self.conv1 = nn.Conv2d(3, 6, 5)        self.pool = nn.MaxPool2d(2, 2)        self.conv2 = nn.Conv2d(6, 16, 5)        self.fc1 = nn.Linear(16 * 5 * 5, 120)        self.fc2 = nn.Linear(120, 84)        self.fc3 = nn.Linear(84, 10)    def forward(self, x):        x = self.pool(F.relu(self.conv1(x)))        x = self.pool(F.relu(self.conv2(x)))        x = x.view(-1, 16 * 5 * 5)        x = F.relu(self.fc1(x))        x = F.relu(self.fc2(x))        x = self.fc3(x)        return x

以一個最簡單的五層網絡為例。需要維持狀態的,主要是兩個卷積和三個線性變換,所以在構造Module是,定義了兩個Conv2d和三個nn.Linear對象,而在計算時,relu之類不需要保存狀態的可以直接使用。

參考地址(這個只是個人筆記,不做商業):

https://blog.csdn.net/tsyccnh/article/details/79163834

https://www.zhihu.com/question/66782101

https://blog.csdn.net/weixin_39190382/article/details/114433884)

https://blog.csdn.net/Fcc_bd_stars/article/details/105158215

標簽:

今日熱點

熱點排行

最近更新

所刊載信息部分轉載自互聯網,并不代表本網贊同其觀點和對其真實性負責。郵箱:5855973@qq.com

聯系我們| 中國品牌網 | 滬ICP備2022005074號-18 營業執照  Copyright © 2018@. All Rights Reserved.

久久国内精品视频,激情懂色av一区av二区av,国产精品无码永久免费888,欧美日韩国产精品自在自线
国产精品yjizz| 在线一区二区三区四区| 亚洲欧美日韩第一区| 国产精品v欧美精品v日韩| 艳妇臀荡乳欲伦亚洲一区| 亚洲欧洲日本在线| 欧美在线观看视频在线| 欧美日韩一区二区三区| 噜噜爱69成人精品| 99视频在线精品国自产拍免费观看| 牛夜精品久久久久久久99黑人| 亚洲欧美激情诱惑| 久久xxxx精品视频| 欧美午夜精品久久久久久人妖| 一本色道综合亚洲| 一区二区三区国产盗摄| 欧美午夜精品一区二区三区| 亚洲国产精品一区二区第四页av| 美女露胸一区二区三区| 亚洲美女视频在线观看| 欧美激情一级片一区二区| 亚洲电影免费观看高清完整版| 亚洲欧美三级伦理| 亚洲免费视频成人| 欧美三区在线观看| 国产精品免费网站| 国产日韩欧美在线视频观看| 欧美成年人视频网站| 一本久道综合久久精品| 欧美亚洲色图校园春色| 国产欧美日韩一区二区三区在线观看| 一本大道久久a久久精品综合| 久久成人资源| 国精产品99永久一区一区| 欧美日韩国产色视频| 欧美一区二区在线免费播放| 欧美高清视频一二三区| 欧美专区在线观看一区| 激情五月***国产精品| 欧美高清视频一区二区三区在线观看| 巨乳诱惑日韩免费av| 国产精品国产三级国产专播精品人| 亚洲三级免费电影| 欧美1区视频| 欧美一区在线直播| 国产精品盗摄一区二区三区| 亚洲宅男天堂在线观看无病毒| 在线观看成人一级片| 欧美在线看片| 91久久精品www人人做人人爽| 亚洲一区网站| 国产精品sm| 国产农村妇女毛片精品久久麻豆| 日韩一区二区精品葵司在线| 欧美国产精品| 欧美日韩裸体免费视频| 欧美图区在线视频| 国产精品成人免费精品自在线观看| 国产日韩一级二级三级| 欧美大片免费观看在线观看网站推荐| 国户精品久久久久久久久久久不卡| 牛牛影视久久网| 日韩一级裸体免费视频| 久久久91精品| 国产日产欧美精品| 久久精品国产欧美激情| 欧美日韩视频在线一区二区观看视频| 久久在线视频在线| 国产日韩在线亚洲字幕中文| 免费成人高清在线视频| 国产精品久久999| 久久人人97超碰精品888| 欧美日韩国语| 欧美日韩专区| 久久久精品动漫| 国产精品a久久久久久| 久久天天躁狠狠躁夜夜av| 欧美三级欧美一级| 一区二区三区欧美激情| 国产精品v欧美精品∨日韩| 国产精品久久久久久久久久尿| 欧美在线免费看| 99re66热这里只有精品3直播| 久久久蜜桃精品| 欧美激情一区| 国产精品第一区| 亚洲午夜激情网页| av成人免费在线观看| 性久久久久久久久久久久| 久久精品国产视频| 性做久久久久久| 久久国产精品亚洲77777| 欧美伊人久久久久久久久影院| 亚洲国产精品电影| 久久久久久香蕉网| 欧美一区二区在线视频| 欧美日韩国产影院| 亚洲欧美日韩一区二区| 久久精品国产第一区二区三区| 欧美日韩一区二区三区在线看| 亚洲一区二区三区成人在线视频精品| 99精品欧美一区二区三区综合在线| 久久综合伊人77777蜜臀| 国产美女精品一区二区三区| 国产综合亚洲精品一区二| 激情文学综合丁香| 久久蜜桃香蕉精品一区二区三区| 欧美日韩日本网| 久久亚洲春色中文字幕久久久| 国产目拍亚洲精品99久久精品| 免费一区视频| 亚洲经典三级| 国产精品日本欧美一区二区三区| 美女在线一区二区| 国产精品成人在线观看| 欧美日韩喷水| 欧美一区二区在线看| 99精品欧美一区二区蜜桃免费| 欧美色播在线播放| 国产亚洲人成a一在线v站| 欧美伊人久久久久久午夜久久久久| 国产午夜精品久久久久久久| 国产一区二区毛片| 亚洲国产欧美另类丝袜| 欧美激情二区三区| 亚洲午夜精品福利| 最新成人在线| 最新高清无码专区| 有码中文亚洲精品| 一区二区三区四区在线| 国产精品毛片大码女人| 午夜日韩视频| 午夜性色一区二区三区免费视频| 欧美深夜福利| 嫩草伊人久久精品少妇av杨幂| 久久久久久综合网天天| 久久综合九色| 欧美一区二区三区男人的天堂| 欧美高清在线一区| 国产日韩欧美制服另类| 欧美日韩国产综合视频在线| 亚洲精品资源美女情侣酒店| 中文日韩在线视频| 欧美精品91| 欧美午夜精品久久久久免费视| 美女视频黄免费的久久| 国产精品成人va在线观看| 亚洲一区网站| 国产精品一区二区三区免费观看| 亚洲国产一区二区三区a毛片| 欧美福利专区| 在线精品视频一区二区| 日韩一级片网址| 国产精品99久久久久久有的能看| 欧美日韩国产色视频| 国产精品视频免费在线观看| 亚洲成人在线网| 国产午夜精品全部视频播放| 国产午夜亚洲精品理论片色戒| 欧美调教视频| 久久av免费一区| 国产精品初高中精品久久| 国产精品入口福利| 久久一区视频| 久久精品亚洲乱码伦伦中文| 亚洲高清精品中出| 一二美女精品欧洲| 日韩视频一区二区在线观看| 国产精品美女| 噜噜噜久久亚洲精品国产品小说| 亚洲欧美激情在线视频| 韩国精品在线观看| 亚洲人成网站999久久久综合| 国产欧美精品一区二区三区介绍| 欧美美女操人视频| 伊人久久亚洲美女图片| 亚洲人午夜精品免费| 欧美日韩免费一区二区三区| 国产精品成人国产乱一区| 99视频精品全国免费| 国产亚洲一本大道中文在线| 欧美日精品一区视频| 黄色国产精品一区二区三区| 欧美日韩亚洲综合一区| 欧美精品 国产精品| 国产精品亚洲综合一区在线观看| 久久国产精品电影| 国产三级欧美三级| 久久女同精品一区二区| 另类天堂视频在线观看| 午夜一区二区三区不卡视频| 欧美伦理91| 国产精品成人国产乱一区| 久久se精品一区二区| 在线视频欧美精品| 久久国产精品久久久| 一本综合久久| 久久精品成人| 国产精品欧美一区二区三区奶水| 亚洲欧美日产图|