日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人工智能 > pytorch >内容正文

pytorch

深度学习基础实例与总结

發布時間:2024/3/13 pytorch 61 豆豆
生活随笔 收集整理的這篇文章主要介紹了 深度学习基础实例与总结 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一、神經網絡

1 深度學習

1 什么是深度學習?

簡單來說,深度學習就是一種包括多個隱含層 (越多即為越深)的多層感知機。它通過組合低層特征,形成更為抽象的高層表示,用以描述被識別對象的高級屬性類別或特征。 能自生成數據的中間表示(雖然這個表示并不能被人類理解),是深度學習區別于其它機器學習算法的獨門絕技。
所以,深度學習可以總結成: 通過加深網絡,提取數據深層次特征

2 深度學習與傳統機器學習對比

1)相同點

目的相同:都是利用機器自我學習能力,解決軟件系統的難題

基本問題相同:回歸問題、分類問題、聚類問題

基本流程相同:模型構建數據準備–>模型選擇 -->/訓練–> 模型評估基本流程相同:–>預測

問題領域相同

  • 樣本是否有標簽:監督學習、非監督學習、半監督學習
  • 應用領域:推薦引擎、計算機視覺、自然語言處理、強化學習

評價標準相同

  • 回歸問題:均方誤差;R2值
  • 分類問題:交又熵;查準率、召回率、F1綜合系數
  • 模型泛化能力:過擬合、欠擬合

2)不同點



深度網絡進化過程

3 感知機與神經網絡

1)生物神經元

2)生物神經網絡

3)什么是感知機

感知機(Perceptron),又稱神經元(Neuron,對生物神經元進行了模仿)是神經網絡(深度學習)的起源管法,1958年由康奈爾大學心理學教授弗蘭克·羅森布拉特(Frank Rosenblatt) 提出,它可以接收多個輸入信號,產生一個輸出信號。

其中, x 1 i x_1i x1?i x 2 x_2 x2?稱為輸入, w 1 w_1 w1? w 2 w_2 w2?為權重, θ \theta θ為闖值,y為輸出。

4)感知機的功能

  • 作為分類器/回歸器,實現自我學習
  • 實現邏輯運算包括邏輯或(OR),邏輯和 (AND)
  • 組成神經網絡
(1)實現邏輯和

(2)實現邏輯或

5) 感知機缺陷

感知機的局限在于無法處理“異或”問題(非線性問題)

6)多層感知機

1975年,感知機的“異或”難題才被理論界徹底解決,即通過多個感知機組合來解決該問題,這種模型也叫多層感知機(Multi-Layer Perceptron,MLP)。如下圖所示,神經元節點闖值均設置為0.5。

7)神經網絡

感知機由于結構簡單,完成的功能十分有限。可以將若干個感知機連在一起,形成個級聯網絡結構,這個結構稱為“多層前饋神經網絡” (Multi-layerFeedforward NeuralNetworks)。所謂“前饋”是指將前一層的輸出作為后層的輸入的邏輯結構。每一層神經元僅與下一層的神經元全連接。但在同一層之內神經元彼此不連接,而且跨層之間的神經元,彼此也不相連。

8)神經網絡的功能

1989年,奧地利學者庫爾特·霍尼克 (Kurt Hornik) 等人發表論文證明,對于任意復雜度的連續波萊爾可測函數 (Borel Measurable Function) f f f,僅僅需要一個隱含層,只要這個隱含層包括足夠多的神經元,前饋神經網絡使用擠壓函數 (Squashing Function) 作為激活函數,就可以以任意精度來近似模擬 f f f。如果想增加f的近似精度,單純依靠增加神經元的數目即可實現。這個定理也被稱為通用近似定理(Universal Approximation Theorem)該定理表明,前饋神經網在理論上可近似解決任何問題.

9) 深層網絡優點

其實,神經網絡的結構還有另外一個“進化”方向,那就是朝著“縱深”方向發展,也就是說,減少單層的神經元數量,而增加神經網絡的層數,也就是“深”而“瘦”的網絡模型。

微軟研究院的科研人員就以上兩類網絡性能展開了實驗,實驗結果表明: 增加網絡的層數會顯著提升神經網絡系統的學習性能

10)激活函數

在神經網絡中,將輸入信號的總和轉換為輸出信號的函數被稱為激活函數 (activation function)

為什么要使用激活函數?

激活函數將多層感知機輸出轉換為非線性,使得神經網絡可以任意逼近任何非線性函數,這樣神經網絡就可以應用到眾多的非線性模型中。

如果一個多層網絡,使用連續函數作為激活函數的多層網絡,稱之為“神經網絡”,否則稱為“多層感知機”。所以,激活函數是區別多層感知機和神經網絡的依據。

常見的激活函數

(1)sigmod函數

sigmoid函數也叫Logistic函數,用于隱層神經元輸出,取值范圍為(0,1),它可以將一個實數映射到(0,1)的區間,可以用來做二分類,表達式: f(x) = 1/(1 + e ? x ) e^-x ) e?x))

優點:平滑、易于求導。

缺點:激活函數計算量大,反向傳播求誤差梯度時,求導涉及除法,反向傳播時,很容易就會出現梯度消失的情況,從而無法完成深層網絡的訓練。

(2)tanh雙曲正切函數

優點:平滑、易于求導;輸出均值為0,收斂速度要比sigmoid快,從而可以減少迭代次數
缺點:梯度消失
用途:常用于NLP中

(3)Relu(Rectified Linear Units,修正線性單元)


優點:(1)更加有效率的梯度下降以及反向傳播,避免了梯度爆炸和梯度消失問題(2)計算過程簡單
缺點:小于等于0的部分梯度為0用途:常用于圖像

(4)Softplus

Softplus是對ReLU的平滑逼近解析形式,更巧的是,Softplus函數的導數恰好就是Sigmoid函數。但實際應用效果不如ReLU好

(5)Softmax

Softmax函數定義如下,其中Vi 是分類器前級輸出單元的輸出。i表示類別索引,總的類別個數為Csi表示的是當前元素的指數與所有元素指數和的比值。通過Softmax函數就可以將多分類的輸出數值轉化為相對概率,而這些值的累和為1,常用于神經網絡輸出層。表達式:

4 損失函數

1)什么是損失函數

損失函數(Loss Function),也有稱之為代價函數 (Cost Function),用來度量預測值和實際值之間的差異。

2)損失函數的作用

度量決策函數 f ( x ) f(x) f(x)和實際值之間的差異。

作為模型性能參考。損失函數值越小,說明預測輸出和實際結果(也稱期望輸出)之間的差值就越小,也就說明我們構建的模型越好。

學習的過程,就是不斷通過訓練數據進行預測,不斷調整預測輸出與實際輸出差異,使的損失值最小的過程。

3)常用損失函數

(1)均方誤差(Mean Square error, MSE)損失函數

均方誤差是回歸問題常用的損失函數,它是預測值與目標值之間差值的平方和,其公式和圖像如下所示:

為什么使用誤差的平方?

  • 曲線的最低點是可導的。

  • 越接近最低點,曲線的坡度逐漸放緩,有助于通過當前的梯度來判斷接近最低點的程度(是否逐漸減少步長,以免錯過最低點)。

(2)交叉熵(Cross Entropy)。

交叉熵是Shannon信息論中一個重要概念主要用于度量兩個概率分布間的差異性信息,在機器學習中用來作為分類問題的損失函數。假設有兩個概率分布, t k t_k tk? y k y_k yk?,其交叉函數公式及圖形如下所示:

5 梯度下降算法

1)批量梯度下降

批量梯度下降法(Batch Gradient Descent,BGD)是最原始的形式,它是指在每一次迭代時使用所有樣本來進行梯度的更新。

優點: 一定能得到最優
一次迭代是對所有樣本進行計算,此時利用矩陣進行操作,實現了并行
由全數據集確定的方向能夠更好地代表樣本總 體,從而更準確地朝向極值所在的方向。當目標函數為凸函數時,BGD一定能夠得到全局最優
缺點:速度太慢
當樣本數目 m m m很大時,每選代一步都需要對所有樣本計算,訓練過程會很慢

2)隨機梯度下降

隨機梯度下降法(Stochastic Gradient Descent,SGD)每次選代使用一個樣本來對參數進行更新,使得訓練速度加快。

優點:
由于不是在全部訓練數據上的損失函數,而是在每輪迭代中,隨機優化某一條訓練數據上的損失函數,這樣每一輪參數的更新速度大大加快
缺點:
準確度下降。由于即使在目標函數為強凸函數的情況下,SGD仍舊無法做到線性收斂。
可能會收斂到局部最優,由于單個樣本并不能代表全體樣本的趨勢。
不易于并行實現。

3)小批量梯度下降(優先)

小批量梯度下降(Mini-Batch Gradient Descent,MBGD)是對批量梯度下降以及隨機梯度下降的一個折中辦法。其思想是:每次選代使用指定個(batch size)樣本來對參數進行更新

優點:
通過矩陣運算,每次在一個batch上優化神經網絡參數并不會比單個數據慢太多每次使用一個batch可以大大減小收斂所需要的迭代次數,同時可以使收斂到的結果更加接近梯度下降的效果
缺點:
batchsize的不當選擇可能會帶來一些問題

6 反向傳播

1)什么是正向傳播網絡

前一層的輸出作為后一層的輸入的邏輯結構,每一層神經元僅與下一層的神經元全連接,通過增加神經網絡的層數雖然可為其提供更大的靈活性讓網絡具有更強的表征能力,也就是說,能解決的問題更多,但隨之而來的數量龐大的網絡參數的訓練,一直是制約多層神經網絡發展的一個重要瓶頸。

2)什么是反向傳播

反向傳播 (Backpropagation algorithm)全稱“誤差反向傳播是在深度神經網絡中,根據輸出層輸出值,來反向調整隱藏層權重的一種方法。

3)為什么需要反向傳播

為什么不直接使用梯度下降而使用反向傳播方式更新權重呢?

梯度下降應用于有明確求導函數的情況,或者可以求出誤差的情況(比如線性回歸),我們可以把它看做沒有隱藏層的網絡。但對于多個隱藏層的神經網絡,輸出層可以直接求出誤差來更新參數,但隱藏層的誤差是不存在的,因此不能對它直接應用梯度下降,而是先將誤差反向傳播至隱藏層然后再應用梯度下降。

4)反向傳播算法極簡史

1974年,哈佛大學沃伯斯博士在他的博士論文中,首次提出了 通過誤差的反向傳播來訓練人工神經網絡,以解決神經網絡數量龐大的參數訓練問題。 但是,沃伯斯的工作并沒有得到足夠的重視,因為當時神經網絡正陷入低潮,可謂“生不逢時”。

1986年,由杰弗里·辛頓 (Geoffrey Hinton)和大衛·魯姆哈特 (David Rumelhart)等人在著名學術期刊Nature(自然)上發表了論文“借助誤差反向傳播算法的學習表征(Learning Representations by Back-propagating errors)”,系統而簡潔地闡述了反向傳播算法在神經網絡模型上的應用。反向傳播算法非常好使,它直接把糾錯的運算量降低到只和神經元數目本身成正比的程度。

后來,沃伯斯得到了IEEE(電氣電子工程師學會)神經網絡分會的先驅獎;Geoffrey Hinton與Yoshua Bengio、Yann LeCun (合稱“深度學習三巨頭”)共同獲得了2018年的圖靈獎

二、卷積神經網絡

1. 卷積

1.1 特征圖像寬和高的計算公式


其中,輸入大小為 ( H , W ) (H,W) (H,W),濾波器大小為 ( F H , F W ) (FH,FW) (FH,FW),輸出大小為 ( O H , O W ) (OH,OW) (OH,OW),填充為 P P P,步幅為 S S S

1.2 三維的圖像

1.3 多通道多卷積核的卷積

每個通道先與第一組卷積核執行卷積,然后多通道結果疊加,產生一個輸出

每個通道與下一組卷積核執行卷積產生另一個輸出

有多少組卷積核,就有多少個通道輸出(如右圖,兩組卷積核,產生兩個通道的輸出數據)

1.4 scipy實現卷積實例

scipy版本為1.2.1

from scipy import signal from scipy import misc import numpy as np import matplotlib.pyplot as pltdata = misc.imread('zebra.png', flatten=True)kernel0 = np.array([[-1, 0, 1],[-2, 0, 2],[-1, 0, 1]])kernel1 = np.array([[-1, -2, -1],[0, 0, 0],[1, 2, 1]])conv0 = signal.convolve2d(data, kernel0, boundary='symm', mode='same').astype('int32') conv1 = signal.convolve2d(data, kernel1, boundary='symm', mode='same').astype('int32')plt.figure('convolutional 2D')plt.subplot(1, 3, 1) plt.imshow(data, cmap='gray') plt.xticks([]) plt.yticks([])plt.subplot(1, 3, 2) plt.imshow(conv0, cmap='gray') plt.xticks([]) plt.yticks([])plt.subplot(1, 3, 3) plt.imshow(conv1, cmap='gray') plt.xticks([]) plt.yticks([])plt.show()

2. 卷積神經網絡結構

1)總結結構

通常情況下,卷積神經網絡由若干個卷積層(Convolutional Layer)、激活層(Activation Layer)、池化層 (Pooling Layer) 及全連接層 (FullyConnected Layer)組成。

2)卷積層

它是卷積神經網絡的核心所在,通過卷積運算,達到降維處理和提取特征兩個重要目的。

3)激活層

其作用在于將前一層的線性輸出,通過非線性的激活函數進行處理,這樣用以模擬任意函數,從而增強網絡的表征能力。前面章節中介紹的激活函數如擠壓函數Sigmoid也是可用的,但效果并不好。在深度學習領域,ReLU(Rectified-Linear Unit,修正線性單元)是目前使用較多的激活函數,主要原因是它收斂更快,次要原因在于它部分解決了梯度消失問題。

4)池化層(Pooling Layer)

也稱子采樣層或下采樣層(Subsampling Layer),目的是縮小高、長方向上的空間的運算,以降低計算量,提高泛化能力。如下的示例,將44的矩陣縮小成22的矩陣輸出。

池化層計算:
對于每個輸入矩陣,我們將其切割成若千大小相等的正方形小塊對每一個區塊取最大值或者平均值,并將結果組成一個新的矩陣。

Max池化:對各個參與池化計算的區域取最大值,形成的新矩陣在圖像識別領域,主要使用Max池化。
Average池化:對各個參與池化計算的區域計算平均值。

池化層特點:
沒有要學習的參數。池化層和卷積層不同,沒有要學習的參數。池化只是從目標區域中取最大值(或者平均值),所以不存在要學習的參數;
通道數不發生變化。經過池化運算,輸入數據和輸出數據的通道數不會發生變化;
對微小的位置變化具有魯棒性 (健壯)。輸入數據發生微小偏差時,池化仍會返回相同的結果。

5)全連接層

這個網絡層相當于多層感知機(Multi-Layer Perceptron,簡稱MLP)其在整個卷積神經網絡中起到分類器的作用通過前面多個“卷積-激活-池化”層的反復處理,待處理的數據特性已有了顯著提高:一方面,輸入數據的維度已下降到可用傳統的前饋全連接網絡來處理了,另一方面此時的全連接層輸入的數據已不再是“泥沙俱下、魚龍混雜”,而是經過反復提純過的結果,因此輸出的分類品質要高得多

3 經典CNN介紹

1)LeNet

LeNet是 Yann LeCun在1998年提出,用于解決手寫數字識別的視覺任務。自那時起,CNN的最基本的架構就定下來了: 卷積層、池化層、全連接層。

(1) 網絡結構

(2)主要參數

  • 輸入32*32大小單通道圖像輸入
  • 兩個“卷積-池化層
  • 第一個全連接層神經元數目為500,再接激活函數
  • 第二個全連接層神經元數目為10,得到10維的特征向量,用于10個數字的分類訓練,送入softmaxt分類,得到分類結果的概率

2)AlexNet

AlexNet是2012年ImageNet競賽冠軍獲得者Hinton和他的學生Alex Krizhevsky設計的,把CNN的基本原理應用到了很深很寬的網絡中。

(1)特點

  • 使用ReLU作為激活函數,并驗證其效果在較深的網絡超過了Sigmoid,成功解決了Sigmoid在網絡較深時的梯度彌散問題
  • 使用Dropout(丟棄學習)隨機忽略一部分神經元防止過擬合
  • 在CNN中使用重疊的最大池化。此前CNN中普遍使用平均池化,AlexNet全部使用最大池化,避免平均池化的模糊化效果
  • 提出了LRN (Local Response Normalization,局部正規化)層,對局部神經元的活動創建競爭機制使得其中響應比較大的值變得相對更大,并抑制其他反饋較小的神經元,增強了模型的泛化能力
  • 使用CUDA加速深度卷積網絡的訓練,利用GPU強大的并行計算能力,處理神經網絡訓練時大量的矩陣運算

(2)網絡結構

(3)主要參數

  • AlexNet網絡包含8層,其中前5層為卷積-池化層,后3層為全連接層;輸入224x224x3的圖像,
  • 第一卷積層用96個11x11x3的卷積核對進行濾波,步幅4像素,全連接的每層有4096個神經元,
  • 最后一個完全連接的層的輸出被饋送到1000路SoftMax,它產生超過1000個類別標簽的分布;整個網絡共650000個神經元

3)VGG

(1)簡要介紹

VGG是Visual Geometry Group, Department of Engineering Science,University of Oxford (牛津大學工程科學系視覺幾何組)的縮寫,2014年參ILSVRC(ImageNet Large Scale Visual Recognition Challenge) 2014大賽獲得亞軍(當年冠軍為GoogLeNet,但因為VGG結構簡單,應用性強,所以很多技術人員都喜歡使用基于VGG的網絡)。

(2)主要參數

  • 網絡深度:16~19層
  • 5組卷積-池化層,3個全連接層三個全連接層,前兩層都有4096通道,第三層共1000路及代表1000個標簽類別;最后一層為softmax層
  • 所有卷積層有相同的配置,即卷積核大小為3x3,步長為1,填充為1
  • 池化層區域大小2x2,步長為2

(3)網絡結構

4)GoogleLeNet

其特點主要是GoogleInception

5)ResNet 殘差網絡

(1)簡要介紹

  • ResNet是ILSVRC2015大賽冠軍,在ImageNet測試集上取得了3.57%的錯誤率
  • 更深的網絡結構,采用殘差結構來緩解深度CNN的梯度消失問題

(2)網絡結構

4 小節

本章節介紹了卷積神經網絡(CNN),CNN是深度學習的主要模型在解決復雜工程問題中表現出了良好的性能。卷積神經網絡主要由以下幾層構成

  • 卷積層。執行卷積運算
  • 激活層。對卷積結果執行激活函數運算
  • 池化層。降低數據規模,防止過擬合
  • 全連接層。執行輸出計算

三、圖像處理


3.1 圖像色彩操作

1 圖像色彩調整

1)亮度調整

  • 對HSV空間的V分量進行處理可以實現對圖像亮度的增強
  • 直接將彩色圖像灰度化,也可以得到代表圖像亮度的灰度圖進行圖像處理,計算量比HSV顏色空間變化低。但在HSV空間中進行處理可以得到增強后的彩色圖像

2)飽和度調整

  • 對HSV空間的S分量進行處理可以實現對圖像飽和度的增強。
  • 飽和度的調整通常是在S原始值上乘以一個修正系數
  • 修正系數大于1,會增加飽和度,使圖像的色彩更鮮
  • 明修正系數小于1,會減小飽和度,使圖像看起來比較平淡

3) 色調調整

  • 對HSV空間的H分量進行處理可以實現對圖像色調的增強
  • 色相H的值對應的是一個角度,并且在色相環上循環。所以色相的修正可能會造成顏色的失真
  • 色相的調整通常在H原始值上加上一個小的偏移量,使其在色相環上有小角度的調整。調整后,圖像的色調會變為冷色或者暖色。

2 圖像灰度化

1)什么是圖像灰度化

在RGB模型中,如果R=G=B時,則彩色表示一種灰度顏色,其中R=G=B的值叫灰度值,因此,灰度圖像每個像素只需一個字節存放灰度值 (又稱強度值、亮度值)灰度范圍為0-255。將RGB圖像(彩色圖像)轉換為灰度圖像的過程稱為圖像灰度化處理

2)如何進行圖像灰度化

  • 分量法。將彩色圖像中的三分量的亮度作為三個灰度圖像的灰度值可根據應用需要選取一種灰度圖像。
  • 最大值法。將彩色圖像中的三分量亮度的最大值作為灰度圖的灰度值。
  • 將彩色圖像中的三分量亮度求平均得到一個灰度值。
  • 根據重要性及其它指標,將三個分量以不同的權值進行加權平均。例如,由于人眼對綠色的敏感最高,對藍色敏感最低,因此,按下式對RGB三分量進行加權平均能得到較合理的灰度圖像。

3 二值化與反二值化

1)二值化

二值化闖值處理是將原始圖像處理為僅有兩個值的二值圖像,對于灰度值大于閩值t的像素點,將其灰度值設定為最大值。對于灰度值小于或等于值的像素點,將其灰度值設定為0。

2)反二值化

反二值化闖值處理的結果也是僅有兩個值的二值圖像,對于灰度值大于閥值的像素點,將其值設定為0;對于灰度值小于或等于閩值的像素點,將其值設定為255。

4 直方圖均衡

1)圖像直方圖

  • 灰度直方圖反映的是一幅圖像中各灰度級像素出現的頻率。以灰度級為橫坐標,縱坐標為灰度級的頻率,繪制頻率同灰度級的關系圖就是灰度直方圖。
  • 它是圖像的一個重要特征,反映了圖像灰度分布的情況使用直方圖進行圖像變換是一種基于概率論的處理方法,通過改變圖像的直方圖修改圖像中各像素的灰度值,達到增強圖像視覺效果的目的。
  • 相對于灰度變化只針對單獨的像素點操作,直方圖變化綜合考慮了全圖的灰度值分布。

2)直方圖均衡化

  • 直方圖均衡化將原始圖像的直方圖,即灰度概率分布圖,進行調整,使之變化為均衡分布的樣式,達到灰度級均衡的效果,可以有效增強圖像的整體對比度。
  • 直方圖均衡化能夠自動的計算變化函數,通過該方法自適應得產生有均衡直方圖的輸出圖像。
  • 能夠對圖像過暗、過亮和細節不清晰的圖像得到有效的增強在常用的圖像處理庫中,直方圖操作都有API直接調用實現

5 代碼實現

imread讀取彩色圖像,默認的色彩空間為BGR

1)讀取、寫入、顯示等基本操作

# opencv核心庫 pip3 install opencv-python==3.4.10.37 # opencv貢獻庫 pip3 install opencv-contrib-python==3.4.10.37 import cv2 as cvimg = cv.imread('zebra.png') print(img)# 圖像信息 print(img.shape) # 高度,寬度,通道數# 顯示圖像 cv.imshow("img1", img) cv.imshow("img2", img)# 保存圖像 cv.imwrite('save.png', img)# 主動進入阻塞等待,等待用戶按下按鍵 cv.waitKey() cv.destroyAllWindows()

2)灰度圖像

(1)可逆轉換操作

注意:此方式為慣用法,使用接口來轉換,可以輸出彩色和灰度圖像

import cv2 as cvimg = cv.imread('zebra.png')# 顯示圖像 cv.imshow("RGB", img)img_gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY) cv.imshow("Gray", img_gray)print(img_gray.shape)# 主動進入阻塞等待,等待用戶按下按鍵 cv.waitKey() cv.destroyAllWindows()
(2)不可逆轉換操作

注意:此方式轉為灰度圖像后,就無法輸出彩色圖像了

import cv2 as cvimg = cv.imread('zebra.png', 0) # 1為彩色,0為灰度,默認為:1# 顯示圖像 cv.imshow("RGB", img)# 主動進入阻塞等待,等待用戶按下按鍵 cv.waitKey() cv.destroyAllWindows()

3)直方圖均衡

(1)灰度圖像均衡
import cv2 as cv import numpy as np import matplotlib.pyplot as pltimg = cv.imread('low.jpg', 0)plt.figure('hist')plt.subplot(2, 2, 1) plt.imshow(img, cmap="gray")plt.subplot(2, 2, 2) plt.hist(img.ravel(), bins=256, range=[0, 256])# 直方圖均衡 img_equ = cv.equalizeHist(img) plt.subplot(2, 2, 3) plt.imshow(img_equ, cmap="gray")plt.subplot(2, 2, 4) plt.hist(img_equ.ravel(), bins=256, range=[0, 256]) plt.show()cv.waitKey() cv.destroyAllWindows()

(2)彩色圖像均衡

BGR沒有亮度通道,需要將BGR色彩空間轉為YUV或HSV

import cv2 as cv import numpy as np import matplotlib.pyplot as pltimg = cv.imread('low.jpg') plt.figure('hist')# 原始圖像 plt.subplot(2, 2, 1) plt.imshow(img, cmap="gray")# 原始圖像的直方圖 plt.subplot(2, 2, 2) plt.hist(img.ravel(), bins=256, range=[0, 256])# 直方圖均衡 hsv = cv.cvtColor(img, cv.COLOR_BGR2HSV) # 先 BGR轉HSV hsv[..., 2] = cv.equalizeHist(hsv[..., 2]) # 再亮度均衡化 bgr = cv.cvtColor(hsv, cv.COLOR_HSV2BGR) # 最后再從HSV轉到BGR plt.subplot(2, 2, 3) plt.imshow(bgr, cmap="gray")plt.subplot(2, 2, 4) plt.hist(bgr.ravel(), bins=256, range=[0, 256]) plt.show()cv.waitKey() cv.destroyAllWindows()

4)顏色選擇(提取)

import cv2 as cv import numpy as npim = cv.imread('opencv.jpg') hsv = cv.cvtColor(im, cv.COLOR_BGR2HSV)min_blue = np.array([110, 50, 50]) max_blue = np.array([130, 255, 255])mask = cv.inRange(hsv, min_blue, max_blue)cv.imshow('mask', mask) cv.imshow('ori', im)res = cv.bitwise_and(im, im, mask=mask)cv.imshow('res', res)cv.waitKey() cv.destroyAllWindows()

5)二值化與反二值化

import cv2 as cv import numpy as npim = cv.imread('opencv.jpg', 0) t, binary_im = cv.threshold(im, 127, 255, cv.THRESH_BINARY) # 圖像,閾值,大于閾值時轉到哪個值,二值化cv.imshow('ori', im) cv.imshow('binary', binary_im)cv.waitKey() cv.destroyAllWindows()

import cv2 as cv import numpy as npim = cv.imread('opencv.jpg', 0) t, binary_im = cv.threshold(im, 127, 255, cv.THRESH_BINARY_INV) # 圖像,閾值,大于閾值時轉到哪個值,二值化cv.imshow('ori', im) cv.imshow('binary', binary_im)cv.waitKey() cv.destroyAllWindows()

3.2 圖像形態操作

1 仿射與透視變換

1)仿射變換

仿射變換是指圖像可以通過一系列的幾何變換來實現 平移旋轉鏡像 等多種操作。該變換能夠保持圖像的平直性和平行性。平直性是指圖像經過仿射變換后,直線仍然是直線;平行性是指圖像在完成仿射變換后,平行線仍然是平行線。

(1)平移

x:水平方向移動的像素值
y:豎直方向移動的像素值

import cv2 import numpy as np# 平移 def translate(img, x, y):''':param img: 原始圖像:param x: 變換后圖像的水平像素:param y: 變換后圖像的垂直像素:return:'''# 平移矩陣M = np.float32([[1, 0, x],[0, 1, y]])h, w = img.shape[:2]res = cv2.warpAffine(img, M, (w, h))return resif __name__ == '__main__':img = cv2.imread('low.jpg')cv2.imshow('img', img)res = translate(img, 50, 50)cv2.imshow('img_y50', res)cv2.waitKey()cv2.destroyAllWindows()

(2)鏡像

import cv2img = cv2.imread("low.jpg") img_ver = cv2.flip(img, 0) img_hor = cv2.flip(img, 1)cv2.imshow('img', img) cv2.imshow('img_ver', img_ver) cv2.imshow('img_hor', img_hor)cv2.waitKey() cv2.destroyAllWindows()

(3)旋轉

x x x, y y y是旋轉中心的坐標點.

import cv2 import numpy as np# 旋轉 def rotate(img, angle, center=None):h, w = img.shape[:2]if center is None:center = (w/2, h/2)# 生成旋轉矩陣M = cv2.getRotationMatrix2D(center, angle, 1.0)res = cv2.warpAffine(img, M, (w, h))return resif __name__ == '__main__':img = cv2.imread('low.jpg')cv2.imshow('img', img)res = rotate(img, 45)cv2.imshow('img_y50', res)cv2.waitKey()cv2.destroyAllWindows()

2)透視變換

透視變換是將圖片投影到一個新的視平面,也稱作投影映射。它是二維(x,y)到三維(X,Y,Z),再到另一個二維(x’,y’)空間的映射相對于仿射變換,它提供了更大的靈活性,將一個四邊形區域映射到另一個四邊形區域(不一定是平行四邊形),透視變換可用于圖像形狀校正。

2 圖像算數計算

1)圖像加法

作用:

  • 圖像加法可以用于多幅圖像平均去除噪聲
  • 圖像加法實現水印的疊加:

  • 圖像減法是找出兩幅圖像的差異,可以在連續圖像中可以實現消除背景和運動檢測。

    (1)直接相加

    直接相加會導致圖像非常亮,較暗的無法顯示,所以一般使用按權重相加

    import cv2 as cvimg_low = cv.imread('low.jpg') img_high = cv.imread('high.jpg') img_added = cv.add(img_low, img_high)cv.imshow('img_low', img_low) cv.imshow('img_high', img_high) cv.imshow('img_added', img_added)cv.waitKey() cv.destroyAllWindows()

    (2)按權重相加
    import cv2 as cvimg_low = cv.imread('low.jpg') img_high = cv.imread('high.jpg') img_added = cv.addWeighted(img_low, 0.8, img_high, 0.2, 0)cv.imshow('img_low', img_low) cv.imshow('img_high', img_high) cv.imshow('img_added', img_added)cv.waitKey() cv.destroyAllWindows()

    addWeighted 的第5個參數是亮度調節量,在最終的圖像上加上這個值。

    2)圖像減法

    import cv2 as cvimg_low = cv.imread('low.jpg') img_high = cv.imread('high.jpg') img_added = cv.subtract(img_low, img_high)cv.imshow('img_low', img_low) cv.imshow('img_high', img_high) cv.imshow('img_added', img_added)cv.waitKey() cv.destroyAllWindows()

    3 圖像縮放

    1)圖像縮小

    圖像縮小可以通過刪除矩陣中的元素來實現,例如:下面的例子進行隔行、隔列刪除后,高度、寬度均減小為原來的一半。

    import cv2 import numpy as npimg = cv2.imread('low.jpg') cv2.imshow('img', img)# 縮小 h, w = img.shape[:2] dst_size = (int(w/2), int(h/2)) res = cv2.resize(img, dst_size) cv2.imshow('res', res) cv2.waitKey() cv2.destroyAllWindows()

    2)圖像放大

    圖像放大需要進行像素插入,常用的插值法有最鄰近插值法和雙線性插值法

    • 最鄰近插值法: 直接使用新的像素點(x’, y’)最近的整數坐標灰度值作為該點的值,該方法計算量小,但精確度不高,并且可能破壞圖像中的線性關系
    • 最近鄰插值法: 雙線性插值法:使用新的像素點(x’,y’)最鄰近的四個像素值進行插值計算。
    import cv2 import numpy as npimg = cv2.imread('low.jpg') cv2.imshow('img', img)# 縮小 h, w = img.shape[:2] dst_size = (int(w*2), int(h*2)) res = cv2.resize(img, dst_size, interpolation=cv2.INTER_NEAREST) # 放大時,默認使用雙線性差值,此時是最近鄰插值 cv2.imshow('NEAREST', res) res = cv2.resize(img, dst_size, interpolation=cv2.INTER_LINEAR) # 放大時,默認使用雙線性差值,此時雙線性差值,效果最好 cv2.imshow('NEAREST', res) cv2.waitKey() cv2.destroyAllWindows()

    4 腐蝕與膨脹

    1)腐蝕

    腐蝕是最基本的形態學操作之一,它能夠將圖像的邊界點消除,使圖像沿著邊界向內收縮,也可以將小于指定結構體元素的部分去除。腐蝕用來“收縮”或者“細化二值圖像中的前景,借此實現去除噪聲、元素分割等功能。

    2)膨脹

    圖像膨脹(dilate)是指根據原圖像的形狀,向外進行擴充。如果圖像內兩個對象的距離較近,那么在膨脹的過程中,兩個對象可能會連通在一起。膨脹操作對填補圖像分割后圖像內所存在的空白相當有幫助.

    3)圖像開運算

    開運算進行的操作是先將圖像腐蝕,再對腐蝕的結果進行膨脹。開運算可以用于去噪、計數等。

    4)圖像閉運算

    閉運算是先膨脹、后腐蝕的運算,它有助于關閉前景物體內部的小孔,或去除物體上的小黑點,還可以將不同的前景圖像進行連接

    5)形態學梯度

    形態學梯度運算是用圖像的膨脹圖像減腐蝕圖像的操作,該操作可以獲取原始圖像中前景圖像的邊緣。

    6)禮帽運算

    禮帽運算是用原始圖像減去其開運算圖像的操作。禮帽運算能夠獲取圖像的噪聲信息,或者得到比原始圖像的邊緣更亮的邊緣信息。

    7)黑帽運算

    黑帽運算是用閉運算圖像減去原始圖像的操作。黑帽運算能夠獲取圖像內部的小孔或前景色中的小黑點,或者得到比原始圖像的邊緣更暗的邊緣部分。

    5 圖像裁剪

    1)隨機裁剪

    import cv2 as cv import numpy as npdef random_crop(img, w_, h_):''':param img: 圖像對象:param w_: 裁剪后圖像的寬度:param h_: 裁剪后圖像的高度:return: 返回的新圖像'''h, w = img.shape[0:2]y = np.random.randint(0, h - h_)x = np.random.randint(0, w - w_)return img[y: y+h_+1, x: x+w_+1]if __name__ == '__main__':img = cv.imread('low.jpg')img_crop = random_crop(img, 250, 80)cv.imshow('croped', img_crop)cv.imshow('ori', img)cv.waitKey()cv.destroyAllWindows()

    2)中心裁剪

    import cv2 as cvdef center_crop(img, w_, h_):h, w = img.shape[0:2]start_y = int(h/2-h_/2)start_x = int(w/2-w_/2)end_y = int(h/2+h_/2)end_x = int(w/2+w_/2)return img[start_y:end_y+1, start_x:end_x+1]if __name__ == '__main__':img = cv.imread('low.jpg')img_crop = center_crop(img, 200, 200)cv.imshow('croped', img_crop)cv.imshow('ori', img)cv.waitKey()cv.destroyAllWindows()

    三、Tensorflow

    3.1 Tensorflow概述

    1. 什么是Tensorflow

    TensorFlow由谷歌人工智能團隊谷歌大腦(Google Brain)開發和維護的開源深度學習平臺,是目前人工智能領域主流的開發平臺,在全世界有著廣泛的用戶群體。

    2. Tensorflow的特點

    • 優秀的構架設計,通過“張量流”進行數據傳遞和計算,用戶可以很容易地、可視化地看到張量流動的每一個環節
    • 可輕松地在CPU/GPU上部署,進行分布式計算,為大數據分析提供計算能力的支撐
    • 跨平臺性好,靈活性強。TensorFlow不僅可在Linux、Mac和Windows系統中運行,甚至還可在移動終端下工作

    3. 安裝

    pip3 install tensorflow==1.14.10 # CPU版本 pip3 install tf-nightly-gpu==1.14.10 # GPU版本

    4. Tensorflow的體系結構

    TensorFlow屬于“定義”與“運行”相分離的運行機制。從操作層面以抽象成兩種:模型構建和模型運行

    • 客戶端:用戶編程、執行使用
    • master:用來與客戶端交互,并進行任務調度
    • worker process: 工作節點,每個worker process可以訪問一到多個device
    • device: TF的計算核心,執行計算

    5. 后端邏輯

    6. 基本概念

    1)張量

    張量 (Tensor):多維數組或向量,張量是數據的載體,包含名字、形狀、數據類型等屬性。

    2)數據流

    • 數據流圖(Data Flow Graph)用“結點(nodes)和“線”(edges)的有向圖來描述數學計算
    • “節點”一般用來表示數學操作,也可以表示數據輸入 (feed in)的起點/輸出(push out) 的終點,或者是讀取/寫入持久變量(persistent variable)的終點
    • “線”表示“節點”之間的輸入/輸出關系。這些數據“線”可以輸運多維數據數組,即“張量”(tensor)
    • 一旦輸入端的所有張量準備好,節點將被分配到各種計算設備完成異步并行地執行運算

    3)操作

    • 操作(Operation,簡稱op)指專門執行計算的節點,tensorflow函數或API定義的都是操作。常用操作包括:
      • 標量運算,向量運算,矩陣運算
      • 帶狀態的運算
      • 神經網絡組建
      • 存儲、恢復
      • 控制流
      • 隊列及同步運算

    4)圖和會話

    • 圖(Graph)描述整個程序結構,Tensorflow中所有的計算都構建在圖中
    • 會話(Session)用來執行圖的運算

    5)變量

    • 在Tensorflow中,變量(Variable) 是一種操作,變量是一種特殊的張量能夠進行存儲持久化(張量不能進行持久化),它的值是張量
    • 占位符(placeholder) 是變量占位符,當不能確定變量的值時,可以先聲明一個占位符,真正執行時再傳入變量

    3.2 Tensorflow的基本使用

    1 圖

    • 圖(Graph)描述了計算的過程。TensorFlow 程序通常被組織成一個構建階段和一個執行階段。在構建階段 op 的執行步驟 被描述成一個圖在執行階段使用會話執行執行圖中的 op
    • TensorFlow Python 庫有一個默認圖(default graph),op 構造器可以為其增加節點這個默認圖對許多程序來說已經足夠用了,也可以創建新的圖來描述計算過程
    • 在Tensorflow中,op/session/tensor都有graph屬性
    import tensorflow as tfcon1 = tf.constant(100.0) con2 = tf.constant(200.0) res = tf.add(con1, con2)# 查看默認的圖 default_graph = tf.get_default_graph() print(default_graph)with tf.Session() as sess:print(sess.run(res))print(con1.graph)print(con2.graph)print(res.graph)print(sess.graph)

    程序輸出:
    300.0
    <tensorflow.python.framework.ops.Graph object at 0x0000027EBEA94148>
    <tensorflow.python.framework.ops.Graph object at 0x0000027EBEA94148>
    <tensorflow.python.framework.ops.Graph object at 0x0000027EBEA94148>
    <tensorflow.python.framework.ops.Graph object at 0x0000027EBEA94148>

    2 會話及相關操作

    會話(session)用來執行圖中的計算,并且保存了計算張量對象的上下文
    信息。會話的作用主要有

    • 運行圖結構
    • 分配資源
    • 掌握資源(如變量、隊列、線程)
      一個session只能執行一個圖的運算。可以在會話對象創建時,指定運行的圖。如果在構造會話時未指定圖形參數,則將在會話中使用默認圖。如果在同一進程中使用多個圖(使用tf.graph()創建),則必須為每個圖使用不同的會話,但每個圖可以在多個會話中使用。

    1)創建會話

    tf.Session() # 使用默認的圖

    2)運行

    session.run(fetches, feed_dict=None)

    fetches: 圖中的單個操作,或多個操作的列表
    feed_dict: 運行傳入的參數構成的字典,可以覆蓋之前的值,

    3)關閉

    session.close() import tensorflow as tfcon1 = tf.constant(100.0) con2 = tf.constant(200.0) res = tf.add(con1, con2)# 查看默認的圖 default_graph = tf.get_default_graph() print(default_graph)# 新建一個圖 new_graph = tf.Graph()# op只能加在默認的圖上,可以暫時將新建的圖暫時設為默認的圖,然后再釋放 with new_graph.as_default(): # 臨時設為默認的圖new_opp = tf.constant('hello world!')with tf.Session(graph=new_graph) as sess:# print(sess.run([con1, con2, res]))print(sess.run(new_opp))

    op只能加在默認的圖上,可以暫時將新建的圖暫時設為默認的圖,然后再釋放

    3 張量

    1)張量的階與形狀

    階:張量的維度(數方括號的層數)形狀表示方法

    • 0維:()
    • 1維:(5),1行5個元素
    • 2維:(2,3),2行3列
    • 3維:(2,34)兩個3行4列的矩陣

    2)張量的數據類型

    3)張量的常用屬性

    4)張量類型轉換

    import tensorflow as tftensor_2d = tf.ones([3, 3], dtype='int32') tensor_zero = tf.zeros([3, 3]) tensor_2_string = tf.cast(tensor_zero, tf.string) # 浮點型不能轉換成字符串with tf.Session() as sess:print(tensor_2d.eval())print(tensor_2_string.eval()) # 浮點型不能轉換成字符串,此處報錯

    注意:浮點型不能轉換成字符串

    5)張量形狀的改變

    (1)靜態張量

    在創建一個張量,初始狀態的形狀

    • tf.Tensorget_shape0:獲取Tensor對象的靜態形狀
    • tf.Tensorset shape():更新Tensor對象的靜態形狀

    注意: 轉換靜態形狀的時候,1-D到1-D,2-D到2-D,不能跨階數改變形狀對于已經固定或者設置靜態形狀的張量/變量,不能再次設置靜態形狀

    (2)動態張量

    動態形狀:在運行圖時,動態形狀才是真正用到的,這種形狀是一種描述原始張量在執行過程中的一種張量

    tf.reshape(tf.Tensorshape):創建一個具有不同動態形狀的新張量可以跨緯度轉換,如1D–>2D,1D–>3D

    import tensorflow as tf import numpy as nptensor_2d = tf.placeholder('float32', shape=[None, 4]) data = np.arange(0, 8).reshape(2, 4)new_data = tf.reshape(data, [1, 8])with tf.Session() as sess:print(sess.run(new_data))

    4)張量數學操作

    import tensorflow as tf import numpy as npx = tf.constant(np.arange(1, 5).reshape(2, 2), dtype='float32') y = tf.constant(np.arange(5, 1, -1).reshape(2, 2), dtype='float32')add = tf.add(x, y) matmul = tf.matmul(x, y) log = tf.log(x) reduce_mul = tf.reduce_mean(x, axis=1)z = tf.constant(np.arange(1, 8), dtype='float32') seg = tf.constant([0, 0, 0, 1, 1, 2, 2]) res = tf.segment_sum(z, seg)with tf.Session() as sess:print(x.eval(), y.eval())print(sess.run(add))print(sess.run(matmul))print(sess.run(log))print(sess.run(reduce_mul))print(res.eval())

    輸出:
    [[1. 2.]
    [3. 4.]]

    [[5. 4.]
    [3. 2.]]
    [[6. 6.]
    [6. 6.]]
    [[11. 8.]
    [27. 20.]]
    [[0. 0.6931472]
    [1.0986123 1.3862944]]
    [1.5 3.5]
    [ 6. 9. 13.]

    4 占位符

    不確定張量內容情況下,可以使用占位符先占個位置,然后執行計算時,通過參數傳入具體數據執行計算(通過feed dict參數指定)。placeholder節點被聲明的時候是未初始化的,也不包含數據,如果沒有為它供給數據,則TensorFlow運算的時候會產生錯誤。

    #占位符定義: name = tf.placeholder(dtype, shape=None, name=None) import tensorflow as tf import numpy as nptensor_2d = tf.placeholder('float32', shape=[2, 3]) data = np.arange(0, 6).reshape(2, 3)with tf.Session() as sess:print(sess.run(tensor_2d, feed_dict={tensor_2d: data}))

    占位符數據可變

    import tensorflow as tf import numpy as nptensor_2d = tf.placeholder('float32', shape=[None, 3]) data = np.arange(0, 9).reshape(3, 3)with tf.Session() as sess:print(sess.run(tensor_2d, feed_dict={tensor_2d: data}))

    5 變量

    • 變量是一種op,它的值是張量
    • 變量能夠持久化保存,普通張量則不
    • 可當定義一個變量時,需要在會話中進行初始化
    • 變量創建

    tf.Variable(initial_value=None, name=None)

    import tensorflow as tf import numpy as npvar = tf.Variable(tf.random_normal([3, 4])) init_op = tf.global_variables_initializer() with tf.Session() as sess:sess.run(init_op) # 必須初始化print(var.eval())

    3.3 可視化

    • 可視化是用來查看在Tensorflow平臺下程序運行的過程,包括: 張量變量,操作,數據流,學習過程等,從而方便 TensorFlow 程序的理解調試與優化
    • Tensorflow提供了專門的可視化工具tensorboard,它將tensorflow執行的數據、模型、過程用圖形方式進行顯示。tensorflow在執行過程中可以通過某些操作,將模型、數據、graph等信息,保存到磁盤中的Events文件中去,從而提供給tensorboard進行可視化

    1 啟動tensorboard

    tensorboard --logdir=D:\Project\PythonProject\ML_Learning\summary\

    注意:
    (1)路徑不加引號
    (2)網址:http://localhost:6006/

    2 摘要與事件文件操作

    如果需要將變量/張量在tensorboard中顯示,需要執行以下兩步

    • 收集變量
      tf.summary.scalar(name, tensor) # 收集標量,name為名字,tensor為值
      tf.summary.histogram(name, tensor)# 收集高維度變量參數
      tf.summary.image(name, tensor)# 收集圖片張量
    • 合并變量并寫入事件文件
      merged = tf.summary.merge_all()# 合并所有變量
      summary = sess. run(merged) # 行合并,每次迭代訓練都需要運行
      FileWriter.add_summary(summary,i) # 添加摘要,i表示第幾次的值

    3 最簡單的線型回歸實例

    import tensorflow as tf import numpy as np# 模型 y = 3x + 11# 1.準備數據 x = tf.random_normal([100, 1], mean=1.75, stddev=0.5, name='x_data') y = tf.matmul(x, [[3.0]]) + 11.0# 2.構建模型 y = wx + b weight = tf.Variable(tf.random_normal([1, 1]), name="w", trainable=True) bias = tf.Variable(0.0, name="b", trainable=True) y_pred = tf.matmul(x, weight) + bias# 3.損失函數 loss = tf.reduce_mean(tf.square(y_pred - y), axis=0)# 4. 梯度下降 optimizer = tf.train.GradientDescentOptimizer(0.1).minimize(loss)# 初始化全局變量 init_var = tf.global_variables_initializer()with tf.Session() as sess:sess.run(init_var)print("weight: {}, bias: {}".format(weight.eval(), bias.eval()))for i in range(500):sess.run(optimizer)print("i: {}, weight: {}, bias: {}, loss: {}".format(i, weight.eval()[0, 0], bias.eval(), loss.eval()[0]))

    輸出:
    weight: [[1.7854646]], bias: 0.0
    i: 0, weight: 6.423867225646973, bias: 2.6243207454681396, loss: 9.109596252441406
    i: 1, weight: 7.046351909637451, bias: 3.0945069789886475, loss: 4.743853569030762
    i: 2, weight: 7.123383522033691, bias: 3.241851329803467, loss: 3.4027130603790283
    i: 3, weight: 7.111809730529785, bias: 3.3871138095855713, loss: 3.7377519607543945
    i: 4, weight: 7.076264381408691, bias: 3.4926016330718994, loss: 4.294710159301758
    i: 5, weight: 6.986569404602051, bias: 3.5605499744415283, loss: 3.821505069732666
    i: 6, weight: 6.944016456604004, bias: 3.637892484664917, loss: 3.1669256687164307
    i: 7, weight: 7.036805629730225, bias: 3.7961792945861816, loss: 4.031221866607666
    i: 8, weight: 6.889873504638672, bias: 3.842052698135376, loss: 3.933861494064331
    i: 9, weight: 6.9066009521484375, bias: 3.9894847869873047, loss: 4.430022716522217
    i: 10, weight: 6.641869068145752, bias: 3.951720952987671, loss: 3.121511936187744
    i: 11, weight: 6.720321178436279, bias: 4.120347499847412, loss: 3.2809276580810547

    i: 489, weight: 3.013960599899292, bias: 10.974303245544434, loss: 5.876861541764811e-05
    i: 490, weight: 3.0138514041900635, bias: 10.974569320678711, loss: 4.3935862777289e-05
    i: 491, weight: 3.0136618614196777, bias: 10.974894523620605, loss: 4.670991620514542e-05
    i: 492, weight: 3.013606309890747, bias: 10.975181579589844, loss: 4.826369695365429e-05
    i: 493, weight: 3.013457775115967, bias: 10.975468635559082, loss: 5.3314353863243014e-05
    i: 494, weight: 3.012927770614624, bias: 10.975626945495605, loss: 4.780766539624892e-05
    i: 495, weight: 3.012622594833374, bias: 10.975756645202637, loss: 5.1373455789871514e-05
    i: 496, weight: 3.0128049850463867, bias: 10.976174354553223, loss: 4.308684583520517e-05
    i: 497, weight: 3.0126736164093018, bias: 10.976405143737793, loss: 5.3000025218352675e-05
    i: 498, weight: 3.01277494430542, bias: 10.97690486907959, loss: 4.385461943456903e-05
    i: 499, weight: 3.012420892715454, bias: 10.97700023651123, loss: 3.047487734875176e-05

    3.4 模型的保存在加載

    模型訓練可能是一個很長的過程,如果每次執行預測之前都重新訓練,會非常耗時,所以幾乎所有人工智能框架都提供了模型保存與加載功能,使得模型訓練完成后,可以保存到文件中,供其它程序使用或繼續訓練。

    模型保存與加載通過tf.train.Saver對象完成,實例化對象:

    saver = tf.train.Saver(var_list=None, max_to_keep=5)

    var_list: 要保存和還原的變量,可以是一個dict或一個列表
    max_to_keep:要保留的最近檢查點文件的最大數量。創建新文件時,會刪除較舊的文件(如max_to_keep=5表示保留5個檢查點文件)
    保存: saver.save(sess,/tmp/ckpt/model)
    加載: saver.restore(sess,/tmp/ckpt/model)

    模型保存與加載實例

    import tensorflow as tf import os# 模型 y = 3x + 11# 1.準備數據 x = tf.random_normal([100, 1], mean=1.75, stddev=0.5, name='x_data') y = tf.matmul(x, [[3.0]]) + 11.0# 2.構建模型 y = wx + b weight = tf.Variable(tf.random_normal([1, 1]), name="w", trainable=True) bias = tf.Variable(0.0, name="b", trainable=True) y_pred = tf.matmul(x, weight) + bias# 3.損失函數 loss = tf.reduce_mean(tf.square(y_pred - y))# 4. 梯度下降 optimizer = tf.train.GradientDescentOptimizer(0.1).minimize(loss)# 初始化全局變量 init_var = tf.global_variables_initializer()# 收集數據 tf.summary.scalar('loss', loss) merged = tf.summary.merge_all()# 模型保存對象 saver = tf.train.Saver()with tf.Session() as sess:sess.run(init_var)print("weight: {}, bias: {}".format(weight.eval(), bias.eval()))fw = tf.summary.FileWriter('./summary/', graph=sess.graph)#if os.path.exists('./model/linear_model/checkpoint'):saver.restore(sess, './model/linear_model/')for i in range(100):sess.run(optimizer)summary = sess.run(merged)fw.add_summary(summary, i)print("i: {}, weight: {}, bias: {}, loss: {}".format(i, weight.eval()[0, 0], bias.eval(), loss.eval()))# 訓練結束之后保存saver.save(sess, './model/linear_model/')

    3.5 文件讀取機制

    TensorFlow文件讀取分為三個步驟:
    第一步:將要讀取的文件放入文件名隊列
    第二步:讀取文件內容,并實行解碼
    第三步:批處理,按照指定筆數構建成一個批次取出

    • 文件隊列構造:生成一個先入先出的隊列,文件閱讀器會需要它來讀取數據
    tf.train.string_input_producer(string_tensor, shuffle=True)

    string_tensor:含有文件名的一階張量
    shuffle:是否打亂文件順序
    返回:文件隊列

    3 文件讀取

    • 文本文件讀取
    tf.TextLineReader

    讀取CSV文件,默認按行讀取

    • 二進制文件讀取
    tf.FixedLengthRecordReader(record_bytes)

    讀取每個記錄是固定字節的二進制文件

    • record_bytes:每次讀取的字節數
    • 通用讀取方法
    read(file_queue)

    從隊列中讀取指定數量(行,字節)的內容
    返回值:一個tensor元組, (文件名, value)

    4 文件內容解碼

    • 解碼文本文件
    tf.decode_csv(records, record_defaults)

    將CSV文件內容轉換為張量,與tf.TextLineReader搭配使用

    • records:字符串,對應文件中的一行
    • record_defaults:類型

    返回:tensor對象列表

    • 解碼二進制文件
    tf.decode_raw(input_bytes,out_type)

    將字節轉換為由數字表示的張量,與tf.FixedLengthRecordReader搭配使用

    • input_bytes: 待轉換字節
    • out_type:輸出類型

    返回: 轉換結果

    5 讀取csv文件

    import os import tensorflow as tfdef read_csv(filelist):# 1.構造文件隊列file_queue = tf.train.string_input_producer(filelist)# 2.定義文件讀取器reader = tf.TextLineReader()# 3.讀取數據filename, data = reader.read(file_queue)# 4.解碼records = [["None"], ["None"]]example, label = tf.decode_csv(data, records)# 5.分批次輸出example_bat, label_bat = tf.train.batch([example, label], batch_size=10, num_threads=1) # batch_size: 一批次讀取數據的大小return (example_bat, label_bat)if __name__ == '__main__':# 構建文件列表dir_name = './data/'file_names = os.listdir(dir_name)file_list = [os.path.join(dir_name, file_name) for file_name in file_names]ret_example_bat, ret_label_bat = read_csv(file_list)with tf.Session() as sess:# 定義線程協調器coord = tf.train.Coordinator()# 開啟文件讀取線程threads = tf.train.start_queue_runners(sess, coord)print(sess.run([ret_example_bat, ret_label_bat]))coord.request_stop()coord.join(threads)

    6 讀取圖像

    1)圖像文件讀取API(全文件讀取器)

    圖像讀取器

    tf.WholeFileReader

    `功能::將文件的全部內容作為值輸出的reader

    read方法:讀取文件內容,返回文件名和文件內容

    圖像解碼器

    tfimage.decode jpeg(constants) # 解碼jpeg格式 tf.image.decode_png(constants) # 解碼png格式

    返回值:3-D張量,[height, width,channels]

    修改圖像大小

    tf.image.resize(images,size) #

    images: 圖片數據,3-D或4-D張量

    • 3-D:[長,寬,通道]
    • 4-D:[數量,長,寬,通道

    size:1-Dint32張量,[長、寬] (不需要傳通道數)

    2)實例

    import tensorflow as tf import os import matplotlib.pyplot as pltdef read_img(filelist):# 1.構造文件隊列file_queue = tf.train.string_input_producer(filelist)# 2.定義文件讀取器reader = tf.WholeFileReader()# 3.讀取數據filename, data = reader.read(file_queue)# 4.解碼images = tf.image.decode_jpeg(data)# 5.分批次輸出images_resized = tf.image.resize(images, (200, 200))images_resized.set_shape([200, 200, 3])images_bat = tf.train.batch([images_resized], batch_size=10, num_threads=1) # batch_size: 一批次讀取數據的大小return images_batif __name__ == '__main__':# 構建文件列表dir_name = './test_img/'file_names = os.listdir(dir_name)file_list = [os.path.join(dir_name, file_name) for file_name in file_names]images_batch = read_img(file_list)with tf.Session() as sess:# 定義線程協調器coord = tf.train.Coordinator()# 開啟文件讀取線程threads = tf.train.start_queue_runners(sess, coord)res = sess.run(images_batch)coord.request_stop()coord.join(threads)print(res)plt.figure()for i in range(10):plt.subplot(2, 5, i+1)plt.xticks([])plt.yticks([])plt.imshow(res[i].astype('int32'))plt.show()

    3.6 MNIST

    • 手寫數字的數據集,來自美國國家標準與技術研究所(Nationallnstitute of Standards andTechnology,NIST),發布與1998年
    • 樣本來自250個不同人的手寫數字,50%高中學生,50%是人口普查局的工作人員
    • 數字從0~9,圖片大小是28x28像素,訓練數據集包含60000個樣本,測試數據集包含10000個樣本。數據集的標簽是長度為10的一維數組數組中每個元素索引號表示對應數字出現的概率
    • 下載地址:http://yann.lecun.com/exdb/mnist/

    1 基礎版本

    import tensorflow as tf from tensorflow.examples.tutorials.mnist import input_data import numpy as np# 1.數據準備 mnist = input_data.read_data_sets('MNIST_data', one_hot=True)x = tf.placeholder(tf.float32, [None, 784]) y = tf.placeholder(tf.float32, [None, 10])# 2.模型構建 weight = tf.Variable(tf.random_normal([784, 10]), trainable=True) bias = tf.Variable(tf.ones([10]), trainable=True) pred_y = tf.nn.softmax(tf.matmul(x, weight) + bias)# 3.損失函數 cross_entropy = - tf.reduce_sum(y * tf.log(pred_y), reduction_indices=1) # reduction_indices 求和 cost = tf.reduce_mean(cross_entropy)# 4.梯度下降 optimizer = tf.train.GradientDescentOptimizer(0.01).minimize(cost)# 5.定義模型保存對象 saver = tf.train.Saver() model_path = './model/mnist/mnist_model.ckpt'batch_size = 100 # 批次大小 total_batch = int(mnist.train.num_examples / batch_size)# 6.開始執行 with tf.Session() as sess:sess.run(tf.global_variables_initializer())for epoch in range(100):avg_cost = 0.0for i in range(total_batch):# 從訓練集中拿到一個批次的數據batch_xs, batch_ys = mnist.train.next_batch(batch_size)params = {x: batch_xs, y: batch_ys}opt_value, costs_value = sess.run([optimizer, cost], feed_dict=params)avg_cost += (costs_value / total_batch)print('epoch:{}, cost: {}'.format(epoch+1, avg_cost))print("訓練結束")# 模型評估corr_pre = tf.equal(tf.argmax(pred_y, 1), tf.argmax(y, 1))acc = tf.reduce_mean(tf.cast(corr_pre, tf.float32))acc_res = acc.eval({x: mnist.test.images, y: mnist.test.labels})save_path = saver.save(sess, model_path)print("準確率:", acc_res)print("模型已保存至:", save_path)# 測試 with tf.Session() as sess:sess.run(tf.global_variables_initializer())saver.restore(sess, model_path)# 從測試集讀取樣本batch_xs, batch_ys = mnist.test.next_batch(10)output = tf.argmax(pred_y, 1)out_val, pred_label = sess.run([output, pred_y], feed_dict={x: batch_xs, y: batch_ys})print('預測結果:', out_val)print("真實結果: ", np.argmax(batch_ys, axis=1))

    2 增量訓練+結果顯示版本

    import tensorflow as tf from tensorflow.examples.tutorials.mnist import input_data import numpy as np import os import matplotlib.pyplot as plt# 1.數據準備 mnist = input_data.read_data_sets('MNIST_data', one_hot=True)x = tf.placeholder(tf.float32, [None, 784]) y = tf.placeholder(tf.float32, [None, 10])# 2.模型構建 weight = tf.Variable(tf.random_normal([784, 10]), trainable=True) bias = tf.Variable(tf.ones([10]), trainable=True) pred_y = tf.nn.softmax(tf.matmul(x, weight) + bias)# 3.損失函數 cross_entropy = - tf.reduce_sum(y * tf.log(pred_y), reduction_indices=1) # reduction_indices 求和 cost = tf.reduce_mean(cross_entropy)# 4.梯度下降 optimizer = tf.train.GradientDescentOptimizer(0.01).minimize(cost)# 5.定義模型保存對象 saver = tf.train.Saver() model_path = './model/mnist/'batch_size = 100 # 批次大小 total_batch = int(mnist.train.num_examples / batch_size)# 6.開始執行 with tf.Session() as sess:sess.run(tf.global_variables_initializer())if os.path.exists('./model/mnist/checkpoint'):saver.restore(sess, model_path)for epoch in range(100): # 訓練100輪avg_cost = 0.0for i in range(total_batch):# 從訓練集中拿到一個批次的數據batch_xs, batch_ys = mnist.train.next_batch(batch_size)params = {x: batch_xs, y: batch_ys}opt_value, costs_value = sess.run([optimizer, cost], feed_dict=params)avg_cost += (costs_value / total_batch)print('epoch:{}, cost: {}'.format(epoch+1, avg_cost))print("訓練結束")# 模型評估corr_pre = tf.equal(tf.argmax(pred_y, 1), tf.argmax(y, 1))acc = tf.reduce_mean(tf.cast(corr_pre, tf.float32))acc_res = acc.eval({x: mnist.test.images, y: mnist.test.labels})save_path = saver.save(sess, model_path)print("準確率:", acc_res)print("模型已保存至:", save_path)# 測試 with tf.Session() as sess:sess.run(tf.global_variables_initializer())saver.restore(sess, model_path)# 從測試集讀取樣本batch_xs, batch_ys = mnist.test.next_batch(10)output = tf.argmax(pred_y, 1)out_val, pred_label = sess.run([output, pred_y], feed_dict={x: batch_xs, y: batch_ys})print('預測結果:', out_val)real_ret = np.argmax(batch_ys, axis=1)print("真實結果: ", real_ret)plt.figure('num')for i in range(10):plt.subplot(2, 5, i+1)plt.xticks([])plt.yticks([])plt.imshow(batch_xs[i].reshape(-1, 28))plt.title('pred:{}, real:{}'.format(out_val[i], real_ret[i]))plt.show()

    總結

    以上是生活随笔為你收集整理的深度学习基础实例与总结的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。