第一章:Python入門
本書使用的程式
NumPy是計算數值用的函式庫
l 在命令提示字元輸入pip install numpy,下載並安裝NumPy。
l NumPy一維矩陣:
import numpy
x = numpy.array([1.0, 2.0, 3.0])
print(x) à [1. 2. 3.]
print(type(x)) à <class 'numpy.ndarray'>
# x矩陣的形狀
print(numpy.ndim(x)) à 1
print(x.shape) à (3,)
print(x.size) à 3
print(x.reshape(3, 1)) à [[1.]
[2.]
[3.]]
# x矩陣的元素資料型態
print(x.dtype) à float64
import numpy
x = numpy.array([1.0, 2.0, 3.0])
print(x) à [1. 2. 3.]
print(type(x)) à <class 'numpy.ndarray'>
# x矩陣的形狀
print(numpy.ndim(x)) à 1
print(x.shape) à (3,)
print(x.size) à 3
print(x.reshape(3, 1)) à [[1.]
[2.]
[3.]]
# x矩陣的元素資料型態
print(x.dtype) à float64
l NumPy多維矩陣:
import numpy
x = numpy.array([[1, 2], [3, 4], [5, 6]])
print(x) à [[1 2]
[3 4]
[5 6]]
print(type(x)) à <class 'numpy.ndarray'>
# x矩陣的形狀
print(numpy.ndim(x)) à 2
print(x.shape) à (3, 2)
print(x.size) à 6
print(x.reshape(2, 3)) à [[1 2 3]
[4 5 6]]
print(x.reshape(2, -1)) à [[1 2 3]
[4 5 6]]
# x矩陣的元素資料型態
print(x.dtype) à int32
import numpy
x = numpy.array([[1, 2], [3, 4], [5, 6]])
print(x) à [[1 2]
[3 4]
[5 6]]
print(type(x)) à <class 'numpy.ndarray'>
# x矩陣的形狀
print(numpy.ndim(x)) à 2
print(x.shape) à (3, 2)
print(x.size) à 6
print(x.reshape(2, 3)) à [[1 2 3]
[4 5 6]]
print(x.reshape(2, -1)) à [[1 2 3]
[4 5 6]]
# x矩陣的元素資料型態
print(x.dtype) à int32
l NumPy算術運算:
import numpy
# 對應元素(Element-wise),元素數量必須相同
x = numpy.array([1.0, 2.0, 3.0])
y = numpy.array([2.0, 4.0, 6.0])
print(x + y) à [3. 6. 9.]
print(x * y) à [ 2. 8. 18.]
a = numpy.array([[1, 2], [3, 4]])
b = numpy.array([[2, 4], [6, 8]])
print(a - b) à [[-1 -2]
[-3 -4]]
print(a / b) à [[0.5 0.5]
[0.5 0.5]]
import numpy
# 對應元素(Element-wise),元素數量必須相同
x = numpy.array([1.0, 2.0, 3.0])
y = numpy.array([2.0, 4.0, 6.0])
print(x + y) à [3. 6. 9.]
print(x * y) à [ 2. 8. 18.]
a = numpy.array([[1, 2], [3, 4]])
b = numpy.array([[2, 4], [6, 8]])
print(a - b) à [[-1 -2]
[-3 -4]]
print(a / b) à [[0.5 0.5]
[0.5 0.5]]
l NumPy算術運算-廣播(Broadcast):
import numpy
x = numpy.array([1.0, 2.0, 3.0])
print(x * 10.0) à [10. 20. 30.]
a = numpy.array([[1, 2], [3, 4]])
b = numpy.array([10, 20])
print(a / b) à [[0.1 0.1]
[0.3 0.2]]
import numpy
x = numpy.array([1.0, 2.0, 3.0])
print(x * 10.0) à [10. 20. 30.]
a = numpy.array([[1, 2], [3, 4]])
b = numpy.array([10, 20])
print(a / b) à [[0.1 0.1]
[0.3 0.2]]
l NumPy矩陣乘積:
import numpy
x = numpy.array([[1, 2], [3, 4], [5, 6]])
y = numpy.array([[7, 8, 9], [10, 11, 12]])
print(numpy.dot(x, y)) à [[ 27 30 33]
[ 61 68 75]
[ 95 106 117]]
import numpy
x = numpy.array([[1, 2], [3, 4], [5, 6]])
y = numpy.array([[7, 8, 9], [10, 11, 12]])
print(numpy.dot(x, y)) à [[ 27 30 33]
[ 61 68 75]
[ 95 106 117]]
l NumPy矩陣轉換:
import numpy
x = numpy.array([[1, 2], [3, 4], [5, 6]])
# x矩陣轉換為一維矩陣
print(x.flatten()) à [1 2 3 4 5 6]
# x矩陣轉換為轉置矩陣
print(x.T) à [[1 3 5]
[2 4 6]]
# x矩陣依指定順序轉換
print(x.transpose(1, 0)) à [[1 3 5]
[2 4 6]]
import numpy
x = numpy.array([[1, 2], [3, 4], [5, 6]])
# x矩陣轉換為一維矩陣
print(x.flatten()) à [1 2 3 4 5 6]
# x矩陣轉換為轉置矩陣
print(x.T) à [[1 3 5]
[2 4 6]]
# x矩陣依指定順序轉換
print(x.transpose(1, 0)) à [[1 3 5]
[2 4 6]]
l NumPy存取元素:
import numpy
x = numpy.array([[51, 55], [14, 19], [0, 4]])
print(x[0]) à [51 55]
print(x[0][1]) à 55
print(x[0, [0, 1]]) à [51 55]
print(x[0, [1]]) à [55]
print(x[[0, 1]]) à [[51 55]
[14 19]]
print(x[[1]]) à [[14 19]]
# 取出15以上的值
print(x > 15) à [[ True True]
[False True]
[False False]]
print(x[x > 15]) à [51 55 19]
import numpy
x = numpy.array([[51, 55], [14, 19], [0, 4]])
print(x[0]) à [51 55]
print(x[0][1]) à 55
print(x[0, [0, 1]]) à [51 55]
print(x[0, [1]]) à [55]
print(x[[0, 1]]) à [[51 55]
[14 19]]
print(x[[1]]) à [[14 19]]
# 取出15以上的值
print(x > 15) à [[ True True]
[False True]
[False False]]
print(x[x > 15]) à [51 55 19]
l NumPy隨機取出元素:
import numpy
x = numpy.array([51, 55, 14, 19, 0, 4])
# 隨機取出3個值,引數replace決定是否重複取出
print(numpy.random.choice(x, 3, replace = True)) à [19 51 19]
# 隨機產出符合均勻分布的3*4矩陣
print(numpy.random.rand(3, 4)) à
[[0.5219055 0.79764018 0.31651997 0.60690332]
[0.73189512 0.43294656 0.54283599 0.9800219 ]
[0.60972101 0.29953073 0.39183258 0.22247915]]
import numpy
x = numpy.array([51, 55, 14, 19, 0, 4])
# 隨機取出3個值,引數replace決定是否重複取出
print(numpy.random.choice(x, 3, replace = True)) à [19 51 19]
# 隨機產出符合均勻分布的3*4矩陣
print(numpy.random.rand(3, 4)) à
[[0.5219055 0.79764018 0.31651997 0.60690332]
[0.73189512 0.43294656 0.54283599 0.9800219 ]
[0.60972101 0.29953073 0.39183258 0.22247915]]
Matplotlib是繪圖用的函式庫
l 在命令提示字元輸入pip install matplotlib,下載並安裝Matplotlib。
l 繪製圖表:
import numpy as np
import matplotlib.pyplot as plt
# 從0到6,以0.1為單位產生資料
x = np.arange(0, 6, 0.1)
y1 = np.sin(x)
y2 = np.cos(x)
plt.plot(x, y1, label = "sin")
plt.plot(x, y2, linestyle = "--", label = "cos")
plt.legend()
plt.xlabel("x")
plt.ylabel("y")
plt.title("sin & cos")
plt.show()
import numpy as np
import matplotlib.pyplot as plt
# 從0到6,以0.1為單位產生資料
x = np.arange(0, 6, 0.1)
y1 = np.sin(x)
y2 = np.cos(x)
plt.plot(x, y1, label = "sin")
plt.plot(x, y2, linestyle = "--", label = "cos")
plt.legend()
plt.xlabel("x")
plt.ylabel("y")
plt.title("sin & cos")
plt.show()
l 顯示影像:
import matplotlib.pyplot as plt
from matplotlib.image import imread
img = imread("test.png")
plt.imshow(img)
plt.show()
import matplotlib.pyplot as plt
from matplotlib.image import imread
img = imread("test.png")
plt.imshow(img)
plt.show()
第二章:感知器
感知器
l 及(AND)、反及(NAND)、或(OR)使用單層感知器,單層感知器在於只能表現用一條直線劃分的區域:
import numpy as np
def perceptron(x1, x2):
x = np.array([x1, x2])
w = np.array([0.3, 0.7])
b = -0.7
tmp = np.sum(x*w) + b
if tmp <= 0:
return 0
else:
return 1
import numpy as np
def perceptron(x1, x2):
x = np.array([x1, x2])
w = np.array([0.3, 0.7])
b = -0.7
tmp = np.sum(x*w) + b
if tmp <= 0:
return 0
else:
return 1
l 互斥或(XOR)必須使用多層感知器:
def XOR(x1, x2):
s1 = NAND(x1, x2)
s2 = OR(x1, x2)
y = AND(s1, s2)
return y
def XOR(x1, x2):
s1 = NAND(x1, x2)
s2 = OR(x1, x2)
y = AND(s1, s2)
return y
第三章:神經網路
活化函數(Activation Function)
l 感知器採用了階梯(Step)函數做為活化函數(非線性函數),神經網路則採用了Sigmoid函數、ReLU函數等做為活化函數,用以處理神經元送來的訊號。
l Step函數:
import numpy as np
def step(x):
return np.array(x > 0, dtype = np.int)
import numpy as np
def step(x):
return np.array(x > 0, dtype = np.int)
l Step函數的圖表:
import numpy as np
import matplotlib.pylab as plt
def step(x):
return np.array(x > 0, dtype = np.int)
x = np.arange(-5.0, 5.0, 0.1)
y = step(x)
plt.plot(x, y)
plt.show()
import numpy as np
import matplotlib.pylab as plt
def step(x):
return np.array(x > 0, dtype = np.int)
x = np.arange(-5.0, 5.0, 0.1)
y = step(x)
plt.plot(x, y)
plt.show()
l Sigmoid函數:
import numpy as np
def sigmoid(x):
return 1 / (1 + np.exp(-x))
import numpy as np
def sigmoid(x):
return 1 / (1 + np.exp(-x))
l Sigmoid函數的圖表:
import numpy as np
import matplotlib.pylab as plt
def sigmoid(x):
return 1 / (1 + np.exp(-x))
x = np.arange(-5.0, 5.0, 0.1)
y = sigmoid(x)
plt.plot(x, y)
plt.show()
import numpy as np
import matplotlib.pylab as plt
def sigmoid(x):
return 1 / (1 + np.exp(-x))
x = np.arange(-5.0, 5.0, 0.1)
y = sigmoid(x)
plt.plot(x, y)
plt.show()
l ReLU函數:
import numpy as np
def relu(x):
return np.maximum(0, x)
import numpy as np
def relu(x):
return np.maximum(0, x)
l ReLU函數的圖表:
import numpy as np
import matplotlib.pylab as plt
def relu(x):
return np.maximum(0, x)
x = np.arange(-5.0, 5.0, 0.1)
y = relu(x)
plt.plot(x, y)
plt.show()
import numpy as np
import matplotlib.pylab as plt
def relu(x):
return np.maximum(0, x)
x = np.arange(-5.0, 5.0, 0.1)
y = relu(x)
plt.plot(x, y)
plt.show()
神經網路輸出層的活化函數
l 神經網路可以用來解決回歸問題與分類問題,回歸問題要使用恆等函數,分類問題要使用Softmax函數。
l 恆等函數是將輸入直接輸出。
l Softmax函數的輸出是0到1之間的實數,且輸出總合為1,故Softmax函數的輸出可以解釋為機率:
import numpy as np
def softmax(a):
# 變數c為防止計算過大數值而產生溢位
c = np.max(a)
expA = np.exp(a - c)
sumExpA = np.sum(expA)
y = expA / sumExpA
return y
import numpy as np
def softmax(a):
# 變數c為防止計算過大數值而產生溢位
c = np.max(a)
expA = np.exp(a - c)
sumExpA = np.sum(expA)
y = expA / sumExpA
return y
第四章:神經網路的學習
損失函數(Loss Function)
l 在神經網路的學習中,使用的指標稱作損失函數(Loss Function),一般而言主要使用均方誤差(Mean
Squared Error)或交叉熵誤差(Cross Entropy Error)。
l 均方誤差,y是Softmax函數輸出,t是訓練資料答案,均方誤差小較適合訓練:
import numpy as np
y = [0.1, 0.05, 0.6, 0.0, 0.05, 0.1, 0.0, 0.1, 0.0, 0.0]
t = [0, 0, 1, 0, 0, 0, 0, 0, 0, 0]
def meanSquaredError(y, t):
return 0.5 * np.sum((y-t)**2)
print(meanSquaredError(np.array(y), np.array(t)))
import numpy as np
y = [0.1, 0.05, 0.6, 0.0, 0.05, 0.1, 0.0, 0.1, 0.0, 0.0]
t = [0, 0, 1, 0, 0, 0, 0, 0, 0, 0]
def meanSquaredError(y, t):
return 0.5 * np.sum((y-t)**2)
print(meanSquaredError(np.array(y), np.array(t)))
l 交叉熵誤差,y是Softmax函數輸出,t是訓練資料答案,交叉熵誤差小較適合訓練:
import numpy as np
y = [0.1, 0.05, 0.6, 0.0, 0.05, 0.1, 0.0, 0.1, 0.0, 0.0]
t = [0, 0, 1, 0, 0, 0, 0, 0, 0, 0]
def crossEntropyError(y, t):
# 變數delta是微小值,為防止發生負無限大的情形
delta = 1e-7
return -np.sum(t * np.log(y + delta))
print(crossEntropyError(np.array(y), np.array(t)))
import numpy as np
y = [0.1, 0.05, 0.6, 0.0, 0.05, 0.1, 0.0, 0.1, 0.0, 0.0]
t = [0, 0, 1, 0, 0, 0, 0, 0, 0, 0]
def crossEntropyError(y, t):
# 變數delta是微小值,為防止發生負無限大的情形
delta = 1e-7
return -np.sum(t * np.log(y + delta))
print(crossEntropyError(np.array(y), np.array(t)))
梯度法
l 神經網路的學習就是要讓損失函數產生的誤差達到最小,使用數值微分以利求極值:
import numpy as np
def numericalGradient(f, x)
# 變數h是微小值
h = 1e-4
grad = np.zero_like(x)
for idx in range(x.size):
tmpVal = x[idx]
x[idx] = tmpVal + h
fxh1 = f(x)
x[idx] = tmpVal - h
fxh2 = f(x)
grad[idx] = (fxh1 - fxh2) / (2*h)
x[idx] = tmpVal
return grad
import numpy as np
def numericalGradient(f, x)
# 變數h是微小值
h = 1e-4
grad = np.zero_like(x)
for idx in range(x.size):
tmpVal = x[idx]
x[idx] = tmpVal + h
fxh1 = f(x)
x[idx] = tmpVal - h
fxh2 = f(x)
grad[idx] = (fxh1 - fxh2) / (2*h)
x[idx] = tmpVal
return grad
l 梯度法找出函數最小值,f是要最佳化的函數,initX是預設值,lr是學習率,stepNum是梯度法重複次數:
def gradientDescent(f, initX, lr = 0.01, stepNum = 100)
x = initX
for i in range(stepNum):
grad = numericalGradient(f, x)
x -= lr * grad
return x
def gradientDescent(f, initX, lr = 0.01, stepNum = 100)
x = initX
for i in range(stepNum):
grad = numericalGradient(f, x)
x -= lr * grad
return x
第五章:誤差反向傳播法
誤差反向傳播法
l 與權重參數有關的損失函數梯度,是利用數值微分計算出來,可改用誤差反向傳播法以較良好的效率計算權重參數梯度。
l 誤差反向傳播法的乘法層:
class MulLayer:
def __init__(self):
self.x = None
self.y = None
def forward(self, x, y):
self.x = x
self.y = y
out = x * y
return out
def backward(self, dout):
dx = dout * self.y
dy = dout * self.x
return dx, dy
class MulLayer:
def __init__(self):
self.x = None
self.y = None
def forward(self, x, y):
self.x = x
self.y = y
out = x * y
return out
def backward(self, dout):
dx = dout * self.y
dy = dout * self.x
return dx, dy
l 誤差反向傳播法的加法層:
class AddLayer:
def __init__(self):
pass
def forward(self, x, y):
out = x + y
return out
def backward(self, dout):
dx = dout * 1
dy = dout * 1
return dx, dy
class AddLayer:
def __init__(self):
pass
def forward(self, x, y):
out = x + y
return out
def backward(self, dout):
dx = dout * 1
dy = dout * 1
return dx, dy
l 誤差反向傳播法的Softmax-with-Loss層:
class SoftmaxWithLoss:
def __init__(self):
self.loss = None
self.y = None
self.t = None
def forward(self, x, t):
self.t = t
self.y = softmax(x)
self.loss = crossEntropyError(self.y, self.t)
return self.loss
def backward(self, dout = 1):
batchSize = self.t.shape[0]
dx = (self.y – self.t) / batchSize
return dx
class SoftmaxWithLoss:
def __init__(self):
self.loss = None
self.y = None
self.t = None
def forward(self, x, t):
self.t = t
self.y = softmax(x)
self.loss = crossEntropyError(self.y, self.t)
return self.loss
def backward(self, dout = 1):
batchSize = self.t.shape[0]
dx = (self.y – self.t) / batchSize
return dx
第六章:與學習有關的技巧
取代準確率梯度下降法(Stochastic Gradient Descent,
SGD)
l SGD形成無效率探索路徑的根本原因在於,梯度方向原本就不是指向最小值,因此本章介紹Momentum、AdaGrad、Adam等三種取代SGD的方法:
一、Momentum-特色為使用物體速度的物理定律。
二、AdaGrad-特色為適應各個參數,一邊調整學習率一邊學習。
三、Adam-相當複雜,但直覺來說特色為融合上述兩種手法。
一、Momentum-特色為使用物體速度的物理定律。
二、AdaGrad-特色為適應各個參數,一邊調整學習率一邊學習。
三、Adam-相當複雜,但直覺來說特色為融合上述兩種手法。
Batch Normalization演算法
l 在神經網路中加入Batch Normalization演算法,強制調整活性化的分布:
優點一-增加學習率,可以快速學習。
優點二-不會過度依賴Xavier、He等權重預設值。
優點三-控制過度學習,可以減少Weight Decay、Dropout等方法的必要。
優點一-增加學習率,可以快速學習。
優點二-不會過度依賴Xavier、He等權重預設值。
優點三-控制過度學習,可以減少Weight Decay、Dropout等方法的必要。
第七章:卷積神經網路
卷積神經網路(Convolutional Neural Network, CNN)
l 卷積神經網路的出現可以輸出入三維形狀的空間資料,比較一般神經網路與卷積神經網路組成的層級:
一般神經網路-Affine-ReLU - Affine-ReLU - ... - Affine-Softmax
卷積神經網路-Convolution-ReLU-Pooling - Convolution-ReLU-Pooling - ... - Affine-ReLU - Affine-Softmax,其中Pooling層用以縮小垂直與水平空間的運算,有時會省略
一般神經網路-Affine-ReLU - Affine-ReLU - ... - Affine-Softmax
卷積神經網路-Convolution-ReLU-Pooling - Convolution-ReLU-Pooling - ... - Affine-ReLU - Affine-Softmax,其中Pooling層用以縮小垂直與水平空間的運算,有時會省略
卷積運算
l 執行卷積運算,不使用for迴圈,改使用im2col()函數比較有效率,im2col()函數可以針對權重,輕鬆展開輸入資料,在Caffe及Chainer等深度學習框架中皆有im2col()函數,函數詳細內容可見本書作者Github,路徑為common/util.py。
l 卷積層(Convolution):
import numpy as np
class Convolution:
def __init__(self, W, b, stride = 1, pad = 0):
self.W = W
self.b = b
self.stride = stride
self.pad = pad
def forward(self, x):
FN, FC, FH, FW = self.W.shape
N, C, H, W = x.shape
# 計算輸出資料長寬
out_h = int(1 + (H + 2 * self.pad - FH) / self.stride)
out_w = int(1 + (W + 2 * self.pad - FW) / self.stride)
# 展開輸入資料
col = im2col(x, FH, FW, self.stride, self.pad)
# 展開濾鏡,設定成-1,可以自動整合元素數量
col_W = self.W.reshape(FN, -1).T
out = np.dot(col, col_W) + self.b
# transpose()是更換多維陣列各軸順序的函數
out = out.reshape(N, out_h, out_w, -1).transpose(0, 3, 1, 2)
return out
import numpy as np
class Convolution:
def __init__(self, W, b, stride = 1, pad = 0):
self.W = W
self.b = b
self.stride = stride
self.pad = pad
def forward(self, x):
FN, FC, FH, FW = self.W.shape
N, C, H, W = x.shape
# 計算輸出資料長寬
out_h = int(1 + (H + 2 * self.pad - FH) / self.stride)
out_w = int(1 + (W + 2 * self.pad - FW) / self.stride)
# 展開輸入資料
col = im2col(x, FH, FW, self.stride, self.pad)
# 展開濾鏡,設定成-1,可以自動整合元素數量
col_W = self.W.reshape(FN, -1).T
out = np.dot(col, col_W) + self.b
# transpose()是更換多維陣列各軸順序的函數
out = out.reshape(N, out_h, out_w, -1).transpose(0, 3, 1, 2)
return out
l 池化層(Pooling):
import numpy as np
class Pooling:
def __init__(self, pool_h, pool_w, stride = 1, pad = 0):
self.pool_h = pool_h
self.pool_w = pool_w
self.stride = stride
self.pad = pad
def forward(self, x):
N, C, H, W = x.shape
# 計算輸出資料長寬
out_h = int(1 + (H - self.pool_h) / self.stride)
out_w = int(1 + (W - self.pool_w) / self.stride)
# 展開、調整輸入資料形狀
col = im2col(x, self.pool_h, self.pool_w, self.stride, self.pad)
col = col.reshape(-1, self.pool_h * self.pool_w)
# 最大值
out = np.max(col, axis = 1)
# 調整輸出資料形狀
out = out.reshape(N, out_h, out_w, C).transpose(0, 3, 1, 2)
return out
import numpy as np
class Pooling:
def __init__(self, pool_h, pool_w, stride = 1, pad = 0):
self.pool_h = pool_h
self.pool_w = pool_w
self.stride = stride
self.pad = pad
def forward(self, x):
N, C, H, W = x.shape
# 計算輸出資料長寬
out_h = int(1 + (H - self.pool_h) / self.stride)
out_w = int(1 + (W - self.pool_w) / self.stride)
# 展開、調整輸入資料形狀
col = im2col(x, self.pool_h, self.pool_w, self.stride, self.pad)
col = col.reshape(-1, self.pool_h * self.pool_w)
# 最大值
out = np.max(col, axis = 1)
# 調整輸出資料形狀
out = out.reshape(N, out_h, out_w, C).transpose(0, 3, 1, 2)
return out
沒有留言:
張貼留言