面試題目:欠擬合、過擬合及如何防止過擬合

對于深度學習或機器學習模型而言,我們不僅要求它對訓練數據集有很好的擬合(訓練誤差),同時也希望它可以對未知數據集(測試集)有很好的擬合結果(泛化能力),所產生的測試誤差被稱為泛化誤差。度量泛化能力的好壞,最直觀的表現就是模型的過擬合(overfitting)和欠擬合(underfitting)。過擬合和欠擬合是用于描述模型在訓練過程中的兩種狀態。一般來說,訓練過程會是如下所示的一個曲線圖在這里插入圖片描述

一、什么是欠擬合?

欠擬合是指模型不能在訓練集上獲得足夠低的誤差。換句換說,就是模型復雜度低,模型在訓練集上就表現很差,沒法學習到數據背后的規律。

如何解決欠擬合?

欠擬合基本上都會發生在訓練剛開始的時候,經過不斷訓練之后欠擬合應該不怎么考慮了。但是如果真的還是存在的話,可以通過增加網絡復雜度或者在模型中增加特征,這些都是很好解決欠擬合的方法。

二、什么是過擬合?

過擬合是指訓練誤差和測試誤差之間的差距太大。換句換說,就是模型復雜度高于實際問題,模型在訓練集上表現很好,但在測試集上卻表現很差。模型對訓練集"死記硬背"(記住了不適用于測試集的訓練集性質或特點),沒有理解數據背后的規律,泛化能力差。
在這里插入圖片描述
為什么會出現過擬合現象?

造成原因主要有以下幾種:
1、訓練數據集樣本單一,樣本不足。如果訓練樣本只有負樣本,然后那生成的模型去預測正樣本,這肯定預測不準。所以訓練樣本要盡可能的全面,覆蓋所有的數據類型。
2、訓練數據中噪聲干擾過大。噪聲指訓練數據中的干擾數據。過多的干擾會導致記錄了很多噪聲特征,忽略了真實輸入和輸出之間的關系。
3、模型過于復雜。模型太復雜,已經能夠“死記硬背”記下了訓練數據的信息,但是遇到沒有見過的數據的時候不能夠變通,泛化能力太差。我們希望模型對不同的模型都有穩定的輸出。模型太復雜是過擬合的重要因素。

三、如何防止過擬合?

要想解決過擬合問題,就要顯著減少測試誤差而不過度增加訓練誤差,從而提高模型的泛化能力。我們可以使用正則化(Regularization)方法。那什么是正則化呢?正則化是指修改學習算法,使其降低泛化誤差而非訓練誤差。

常用的正則化方法根據具體的使用策略不同可分為:(1)直接提供正則化約束的參數正則化方法,如L1/L2正則化;(2)通過工程上的技巧來實現更低泛化誤差的方法,如提前終止(Early stopping)和Dropout;(3)不直接提供約束的隱式正則化方法,如數據增強等。

3 1. 獲取和使用更多的數據(數據集增強)——解決過擬合的根本性方法

讓機器學習或深度學習模型泛化能力更好的辦法就是使用更多的數據進行訓練。但是,在實踐中,我們擁有的數據量是有限的。解決這個問題的一種方法就是創建“假數據”并添加到訓練集中——數據集增強。通過增加訓練集的額外副本來增加訓練集的大小,進而改進模型的泛化能力。

我們以圖像數據集舉例,能夠做:旋轉圖像、縮放圖像、隨機裁剪、加入隨機噪聲、平移、鏡像等方式來增加數據量。另外補充一句,在物體分類問題里,CNN在圖像識別的過程中有強大的“不變性”規則,即待辨識的物體在圖像中的形狀、姿勢、位置、圖像整體明暗度都不會影響分類結果。我們就可以通過圖像平移、翻轉、縮放、切割等手段將數據庫成倍擴充。

2. 采用合適的模型(控制模型的復雜度)

過于復雜的模型會帶來過擬合問題。對于模型的設計,目前公認的一個深度學習規律"deeper is better"。國內外各種大牛通過實驗和競賽發現,對于CNN來說,層數越多效果越好,但是也更容易產生過擬合,并且計算所耗費的時間也越長。

根據奧卡姆剃刀法則:在同樣能夠解釋已知觀測現象的假設中,我們應該挑選“最簡單”的那一個。對于模型的設計而言,我們應該選擇簡單、合適的模型解決復雜的問題。

3. 降低特征的數量

對于一些特征工程而言,可以降低特征的數量——刪除冗余特征,人工選擇保留哪些特征。這種方法也可以解決過擬合問題。

4. L1 / L2 正則化

(1) L1 正則化

在原始的損失函數后面加上一個L1正則化項,即全部權重www的絕對值的和,再乘以λ/n。則損失函數變為:

[公式]

對應的梯度(導數):
在這里插入圖片描述

其中 [公式] 只是簡單地取 [公式] 各個元素地正負號。

在這里插入圖片描述

梯度下降時權重 [公式] 更新變為:

w=0w=0w=0時,|w|是不可導的。所以我們僅僅能依照原始的未經正則化的方法去更新w。

w>0w>0w>0時,sgn( www )>0, 則梯度下降時更新后的 www變小。

w<0w<0w<0 時,sgn( www )>0, 則梯度下降時更新后的 www 變大。換句換說,L1正則化使得權重www往0靠,使網絡中的權重盡可能為0,也就相當于減小了網絡復雜度,防止過擬合。

這也就是L1正則化會產生更稀疏(sparse)的解的原因。此處稀疏性指的是最優值中的一些參數為0。L1正則化的稀疏性質已經被廣泛地應用于特征選擇機制,從可用的特征子集中選擇出有意義的特征。

(2) L2 正則化

L2正則化通常被稱為權重衰減(weight decay),就是在原始的損失函數后面再加上一個L2正則化項,即全部權重www的平方和,再乘以λ/2n。則損失函數變為:

對應的梯度(導數):
在這里插入圖片描述
在這里插入圖片描述

能夠發現L2正則化項對偏置 b 的更新沒有影響,可是對于權重 [公式] 的更新有影響:
在這里插入圖片描述

這里的[公式]都是大于0的, 所以[公式] 小于1。因此在梯度下降過程中,權重 www 將逐漸減小,趨向于0但不等于0。這也就是權重衰減(weight decay)的由來。

L2正則化起到使得權重參數www變小的效果,為什么能防止過擬合呢?因為更小的權重參數 www意味著模型的復雜度更低,對訓練數據的擬合剛剛好,不會過分擬合訓練數據,從而提高模型的泛化能力。

5. Dropout

Dropout是在訓練網絡時用的一種技巧(trike),相當于在隱藏單元增加了噪聲。Dropout 指的是在訓練過程中每次按一定的概率(比如50%)隨機地“刪除”一部分隱藏單元(神經元)。所謂的“刪除”不是真正意義上的刪除,其實就是將該部分神經元的激活函數設為0(激活函數的輸出為0),讓這些神經元不計算而已。

Dropout為什么有助于防止過擬合呢?

(a)在訓練過程中會產生不同的訓練模型,不同的訓練模型也會產生不同的的計算結果。隨著訓練的不斷進行,計算結果會在一個范圍內波動,但是均值卻不會有很大變化,因此可以把最終的訓練結果看作是不同模型的平均輸出。

(b)它消除或者減弱了神經元節點間的聯合,降低了網絡對單個神經元的依賴,從而增強了泛化能力。

6. Early stopping(提前終止)

對模型進行訓練的過程即是對模型的參數進行學習更新的過程,這個參數學習的過程往往會用到一些迭代方法,如梯度下降(Gradient descent)。Early stopping是一種迭代次數截斷的方法來防止過擬合的方法,即在模型對訓練數據集迭代收斂之前停止迭代來防止過擬合。

為了獲得性能良好的神經網絡,訓練過程中可能會經過很多次epoch(遍歷整個數據集的次數,一次為一個epoch)。如果epoch數量太少,網絡有可能發生欠擬合;如果epoch數量太多,則有可能發生過擬合。Early stopping旨在解決epoch數量需要手動設置的問題。具體做法:每個epoch(或每N個epoch)結束后,在驗證集上獲取測試結果,隨著epoch的增加,如果在驗證集上發現測試誤差上升,則停止訓練,將停止之后的權重作為網絡的最終參數。

為什么能防止過擬合?當還未在神經網絡運行太多迭代過程的時候,w參數接近于0,因為隨機初始化w值的時候,它的值是較小的隨機值。當你開始迭代過程,w的值會變得越來越大。到后面時,w的值已經變得十分大了。所以early stopping要做的就是在中間點停止迭代過程。我們將會得到一個中等大小的w參數,會得到與L2正則化相似的結果,選擇了w參數較小的神經網絡。

Early Stopping缺點:沒有采取不同的方式來解決優化損失函數和過擬合這兩個問題,而是用一種方法同時解決兩個問題 ,結果就是要考慮的東西變得更復雜。之所以不能獨立地處理,因為如果你停止了優化損失函數,你可能會發現損失函數的值不夠小,同時你又不希望過擬合。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/535180.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/535180.shtml
英文地址,請注明出處:http://en.pswp.cn/news/535180.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

LaTeX:equation, aligned 書寫公式換行,頂部對齊

使用aligined 函數&#xff0c;其中aligned就是用來公式對齊的&#xff0c;在中間公式中&#xff0c;\ 表示換行&#xff0c; & 表示對齊。在公式中等號之前加&&#xff0c;等號介紹要換行的地方加\就可以了。 \begin{equation} \begin{aligned} L_{task} &\lamb…

Latex: 表格中 自動換行居中

1、在導言區添加宏包&#xff1a; \usepackage{makecell}2、環境&#xff1a;tabular 命令&#xff1a; \makecell[居中情況]{第1行內容 \\ 第2行內容 \\ 第3行內容 ...} \makecell [c]{ResNet101\\ (11.7M)}參數說明&#xff1a; [c]是水平居中&#xff0c;[l]水平左居中&am…

argparse:shell向Python中傳參數

一般是 python train.py --bath_size 5利用argparse解析參數 import argparse parser argparse.ArgumentParser() parser.add_argument(integer, typeint, helpdisplay an integer) args parser.parse_args()參數類型 可選參數 import argparse parser argparse.Argumen…

FTP命令:下載,上傳FTP服務器中的文件

步驟 1: 建立 FTP 連接 想要連接 FTP 服務器&#xff0c;在命令上中先輸入ftp然后空格跟上 FTP 服務器的域名 domain.com 或者 IP 地址例如:1.ftp domain.com2.ftp 192.168.0.13.ftp userftpdomain.com注意: 本例中使用匿名服務器。替換下面例子中 IP 或域名為你的服務器地址。…

Tensorflow代碼轉pytorch代碼 函數的轉換

tensoflow函數和pytorch函數之間的轉換 tensorflowpytrochtf.reshape(input, shape)input.view()tf.expand_dims(input, dim)input.unsqueeze(dim) / input.view()tf.squeeze(input, dim)torch.squeeze(dim)/ input.view()tf.gather(input1, input2)input1[input2]tf.tile(inp…

在服務器上遠程使用tensorboard查看訓練loss和準確率

本人使用的是vscode 很簡單 from torch.utils.tensorboard import SummaryWriter writer SummaryWriter(./logs)writer.add_scalar(train_loss,loss.val(),iteration) # 名字&#xff0c;數據&#xff0c;迭代次數訓練的過程中會產生一個./logs的文件夾&#xff0c;里面存放的…

python,pytorch:讀取,保存,顯示圖片

文章目錄一&#xff0c;Pytorch1. 直接保存Tensor2.Tensor 轉CV2 保存二、python1. opencv2.matplotlib:3. PIL一&#xff0c;Pytorch 1. 直接保存Tensor #!/usr/bin/env python # _*_ coding:utf-8 _*_ import torch from torchvision import utils as vutilsdef save_image…

Python循環創建變量名

使用命名空間locals locals 中是當前程序段中的全部變量名是一個字典的形式 所以我們新增的話&#xff0c;直接和字典那樣就行了 names locals() #獲取當前程序段中的全體局部變量名 for i in np.arange(0,10):names[fname_{i}]i

pytorch:固定部分層參數,固定單個模型

文章目錄固定部分層參數固定指定層的參數不同層設置不同的學習率固定部分層參數 class RESNET_attention(nn.Module):def __init__(self, model, pretrained):super(RESNET_attetnion, self).__init__()self.resnet model(pretrained) # 這個model被固定for p in self.parame…

圖片拼接的幾種方法

1. torch tensor 格式 from torchvision.utils import save_imageimg_train_list torch.cat([image_s,image_r,im_G[0],fake_A,mask_s[:, :, 0],mask_r[:, :, 0]])result_path self.save_path_dir/imageif not os.path.exists(result_path):os.makedirs(result_path)save_im…

Pytorch 各種模塊:降低學習率,

1.訓練過程中學習率衰減 if (self.e1) > (self.num_epochs - self.num_epochs_decay):g_lr - (self.g_lr / float(self.num_epochs_decay))d_lr - (self.d_lr / float(self.num_epochs_decay))self.update_lr(g_lr, d_lr)print(Decay learning rate to g_lr: {}, d_lr:{}..…

cudnn.deterministic = True 固定隨機種子

隨機數種子seed確定時&#xff0c;模型的訓練結果將始終保持一致。 隨機數種子seed確定時使用相同的網絡結構&#xff0c;跑出來的效果完全不同&#xff0c;用的學習率&#xff0c;迭代次數&#xff0c;batch size 都是一樣。 torch.backends.cudnn.deterministic是啥&#x…

torch.backends.cudnn.benchmark 加速訓練

設置 torch.backends.cudnn.benchmarkTrue 將會讓程序在開始時花費一點額外時間&#xff0c;為整個網絡的每個卷積層搜索最適合它的卷積實現算法&#xff0c;進而實現網絡的加速。適用場景是網絡結構固定&#xff08;不是動態變化的&#xff09;&#xff0c;網絡的輸入形狀&…

各種損失損失函數的使用場景和使用方法:KL散度

KL 散度的使用場景 KL散度( Kullback–Leibler divergence)&#xff0c;又稱相對熵&#xff0c;是描述兩個概率分布 P 和 Q 差異的一種方法 torch.nn.functional.kl_div(input, target, size_averageNone, reduceNone, reductionmean) torch.nn.KLDivLoss(input, target, si…

RNN,LSTM,GRU的理解

RNN x 為當前狀態下數據的輸入&#xff0c; h 表示接收到的上一個節點的輸入。 y為當前節點狀態下的輸出&#xff0c;而h′h^\primeh′為傳遞到下一個節點的輸出. LSTM #定義網絡 lstm nn.LSTM(input_size20,hidden_size50,num_layers2) #輸入變量 input_data Variable(tor…

常用的loss函數,以及在訓練中的使用

文章目錄KL 散度L2 loss做標準化處理CElossCTCLossAdaptiveAvgPool2dKL 散度 算KL散度的時候要注意前后順序以及加log import torhch.nn as nn d_loss nn.KLDivLoss(reductionreduction_kd)(F.log_softmax(y / T, dim1),F.softmax(teacher_scores / T, dim1)) * T * T蒸餾lo…

Shell 在訓練模型的時候自動保存訓練文件和模型到指定文件夾

在進行深度學習訓練的過程中&#xff0c;往往會跑很多實驗&#xff0c;這就導致有的實驗設置會忘記或者記混淆&#xff0c;我們最好把train test model 的代碼都copy一遍到指定文件夾中&#xff0c;這樣后面檢查也方便。 用shell指令保存文件 #!/bin/sh GRUB_CMDLINE_LINUX&qu…

Pytorch:數據并行和模型并行,解決訓練過程中內存分配不均衡的問題

文章目錄數據并行單機多卡訓練&#xff0c;即并行訓練。并行訓練又分為數據并行 (Data Parallelism) 和模型并行兩種。 數據并行指的是&#xff0c;多張 GPU 使用相同的模型副本&#xff0c;但是使用不同的數據批進行訓練。而模型并行指的是&#xff0c;多張GPU 分別訓練模型的…

DataParallel 和 DistributedDataParallel 的區別和使用方法

1.DataParallel DataParallel更易于使用&#xff08;只需簡單包裝單GPU模型&#xff09;。 model nn.DataParallel(model)它使用一個進程來計算模型參數&#xff0c;然后在每個批處理期間將分發到每個GPU&#xff0c;然后每個GPU計算各自的梯度&#xff0c;然后匯總到GPU0中…

torch.cuda.is_available(),torch.cuda.device_count(),torch.cuda.get_device_name(0)

torch.cuda.is_available() cuda是否可用&#xff1b; torch.cuda.device_count() 返回gpu數量&#xff1b; torch.cuda.get_device_name(0) 返回gpu名字&#xff0c;設備索引默認從0開始&#xff1b; torch.cuda.current_device() 返回當前設備索引&#xff1b;