您好,登錄后才能下訂單哦!
目前數(shù)據(jù)預(yù)處理最常見的方法就是中心化和標(biāo)準(zhǔn)化。
中心化相當(dāng)于修正數(shù)據(jù)的中心位置,實(shí)現(xiàn)方法非常簡單,就是在每個(gè)特征維度上減去對應(yīng)的均值,最后得到 0 均值的特征。
標(biāo)準(zhǔn)化也非常簡單,在數(shù)據(jù)變成 0 均值之后,為了使得不同的特征維度有著相同的規(guī)模,可以除以標(biāo)準(zhǔn)差近似為一個(gè)標(biāo)準(zhǔn)正態(tài)分布,也可以依據(jù)最大值和最小值將其轉(zhuǎn)化為 -1 ~ 1 之間
批標(biāo)準(zhǔn)化:BN
在數(shù)據(jù)預(yù)處理的時(shí)候,我們盡量輸入特征不相關(guān)且滿足一個(gè)標(biāo)準(zhǔn)的正態(tài)分布,這樣模型的表現(xiàn)一般也較好。但是對于很深的網(wǎng)路結(jié)構(gòu),網(wǎng)路的非線性層會使得輸出的結(jié)果變得相關(guān),且不再滿足一個(gè)標(biāo)準(zhǔn)的 N(0, 1) 的分布,甚至輸出的中心已經(jīng)發(fā)生了偏移,這對于模型的訓(xùn)練,特別是深層的模型訓(xùn)練非常的困難。
所以在 2015 年一篇論文提出了這個(gè)方法,批標(biāo)準(zhǔn)化,簡而言之,就是對于每一層網(wǎng)絡(luò)的輸出,對其做一個(gè)歸一化,使其服從標(biāo)準(zhǔn)的正態(tài)分布,這樣后一層網(wǎng)絡(luò)的輸入也是一個(gè)標(biāo)準(zhǔn)的正態(tài)分布,所以能夠比較好的進(jìn)行訓(xùn)練,加快收斂速度。
batch normalization 的實(shí)現(xiàn)非常簡單,接下來寫一下對應(yīng)的python代碼:
import sys sys.path.append('..') import torch def simple_batch_norm_1d(x, gamma, beta): eps = 1e-5 x_mean = torch.mean(x, dim=0, keepdim=True) # 保留維度進(jìn)行 broadcast x_var = torch.mean((x - x_mean) ** 2, dim=0, keepdim=True) x_hat = (x - x_mean) / torch.sqrt(x_var + eps) return gamma.view_as(x_mean) * x_hat + beta.view_as(x_mean) x = torch.arange(15).view(5, 3) gamma = torch.ones(x.shape[1]) beta = torch.zeros(x.shape[1]) print('before bn: ') print(x) y = simple_batch_norm_1d(x, gamma, beta) print('after bn: ') print(y)
測試的時(shí)候該使用批標(biāo)準(zhǔn)化嗎?
答案是肯定的,因?yàn)橛?xùn)練的時(shí)候使用了,而測試的時(shí)候不使用肯定會導(dǎo)致結(jié)果出現(xiàn)偏差,但是測試的時(shí)候如果只有一個(gè)數(shù)據(jù)集,那么均值不就是這個(gè)值,方差為 0 嗎?這顯然是隨機(jī)的,所以測試的時(shí)候不能用測試的數(shù)據(jù)集去算均值和方差,而是用訓(xùn)練的時(shí)候算出的移動(dòng)平均均值和方差去代替
下面我們實(shí)現(xiàn)以下能夠區(qū)分訓(xùn)練狀態(tài)和測試狀態(tài)的批標(biāo)準(zhǔn)化方法
def batch_norm_1d(x, gamma, beta, is_training, moving_mean, moving_var, moving_momentum=0.1): eps = 1e-5 x_mean = torch.mean(x, dim=0, keepdim=True) # 保留維度進(jìn)行 broadcast x_var = torch.mean((x - x_mean) ** 2, dim=0, keepdim=True) if is_training: x_hat = (x - x_mean) / torch.sqrt(x_var + eps) moving_mean[:] = moving_momentum * moving_mean + (1. - moving_momentum) * x_mean moving_var[:] = moving_momentum * moving_var + (1. - moving_momentum) * x_var else: x_hat = (x - moving_mean) / torch.sqrt(moving_var + eps) return gamma.view_as(x_mean) * x_hat + beta.view_as(x_mean)
下面我們在卷積網(wǎng)絡(luò)下試用一下批標(biāo)準(zhǔn)化看看效果
def data_tf(x): x = np.array(x, dtype='float32') / 255 x = (x - 0.5) / 0.5 # 數(shù)據(jù)預(yù)處理,標(biāo)準(zhǔn)化 x = torch.from_numpy(x) x = x.unsqueeze(0) return x train_set = mnist.MNIST('./data', train=True, transform=data_tf, download=True) # 重新載入數(shù)據(jù)集,申明定義的數(shù)據(jù)變換 test_set = mnist.MNIST('./data', train=False, transform=data_tf, download=True) train_data = DataLoader(train_set, batch_size=64, shuffle=True) test_data = DataLoader(test_set, batch_size=128, shuffle=False) # 使用批標(biāo)準(zhǔn)化 class conv_bn_net(nn.Module): def __init__(self): super(conv_bn_net, self).__init__() self.stage1 = nn.Sequential( nn.Conv2d(1, 6, 3, padding=1), nn.BatchNorm2d(6), nn.ReLU(True), nn.MaxPool2d(2, 2), nn.Conv2d(6, 16, 5), nn.BatchNorm2d(16), nn.ReLU(True), nn.MaxPool2d(2, 2) ) self.classfy = nn.Linear(400, 10) def forward(self, x): x = self.stage1(x) x = x.view(x.shape[0], -1) x = self.classfy(x) return x net = conv_bn_net() optimizer = torch.optim.SGD(net.parameters(), 1e-1) # 使用隨機(jī)梯度下降,學(xué)習(xí)率 0.1 train(net, train_data, test_data, 5, optimizer, criterion)
以上這篇pytorch 圖像中的數(shù)據(jù)預(yù)處理和批標(biāo)準(zhǔn)化實(shí)例就是小編分享給大家的全部內(nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持億速云。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。