搭建深度神经网络识别猫

搭建深度神经网络识别猫(Python手写)。

Python代码

1
import time
2
import h5py
3
import numpy as np
4
5
6
# 加载数据
7
def load_data():
8
    train_dataset = h5py.File('datasets/train_catvnoncat.h5', "r")
9
    train_set_x_orig = np.array(train_dataset["train_set_x"][:]) # your train set features
10
    train_set_y_orig = np.array(train_dataset["train_set_y"][:]) # your train set labels
11
    test_dataset = h5py.File('datasets/test_catvnoncat.h5', "r")
12
    test_set_x_orig = np.array(test_dataset["test_set_x"][:]) # your test set features
13
    test_set_y_orig = np.array(test_dataset["test_set_y"][:]) # your test set labels
14
    classes = np.array(test_dataset["list_classes"][:]) # the list of classes
15
    train_set_y_orig = train_set_y_orig.reshape((1, train_set_y_orig.shape[0]))
16
    test_set_y_orig = test_set_y_orig.reshape((1, test_set_y_orig.shape[0]))
17
    return train_set_x_orig, train_set_y_orig, test_set_x_orig, test_set_y_orig, classes
18
19
20
# S激活函数
21
def sigmoid(z):
22
    return 1. / (1.+np.exp(-z))
23
24
25
# RELU激活函数
26
def relu(Z):
27
    A = np.maximum(0,Z)
28
    return A
29
30
31
# Leaky RELU激活函数
32
def leaky_relu(Z):
33
    A = np.maximum(0,Z)
34
    A[Z < 0] = 0.01 * Z
35
    return A
36
37
38
# 深度神经网络模型
39
class DeepNeuralNetwork():
40
    def __init__(self, layers_dim, activations):
41
        np.random.seed(1)
42
        self.layers_dim = layers_dim
43
        self.__num_layers = len(layers_dim)
44
        self.activations = activations
45
        self.input_size = layers_dim[0]
46
        self.parameters = self.__parameters_initializer(layers_dim)
47
        self.output_size = layers_dim[-1]
48
49
    # 参数初始化
50
    def __parameters_initializer(self, layers_dim):
51
        L = len(layers_dim)
52
        parameters = {}
53
        for l in range(1, L):
54
            parameters['W'+str(l)] = np.random.randn(layers_dim[l], layers_dim[l-1]) / np.sqrt(layers_dim[l-1])
55
            parameters['b'+str(l)] = np.zeros((layers_dim[l], 1))
56
        return parameters
57
58
    # 前向传播中的一层
59
    def __one_layer_forward(self, A_prev, W, b, activation):
60
        Z = np.dot(W, A_prev) + b
61
        if activation == 'sigmoid':
62
            A = sigmoid(Z)
63
        if activation == 'relu':
64
            A = relu(Z)
65
        if activation == 'leaky_relu':
66
            A = leaky_relu(Z)
67
        if activation == 'tanh':
68
            A = np.tanh(Z)
69
        cache = {'Z': Z, 'A': A}
70
        return A, cache
71
72
    # 前向传播
73
    def __forward_propagation(self, X):
74
        caches = []
75
        A_prev = X
76
        caches.append({'A': A_prev})
77
        for l in range(1, len(self.layers_dim)):
78
            W, b = self.parameters['W'+str(l)], self.parameters['b'+str(l)]
79
            A_prev, cache = self.__one_layer_forward(A_prev, W, b, self.activations[l-1])
80
            caches.append(cache)
81
        AL = caches[-1]['A']
82
        return AL, caches
83
84
    # 计算损失
85
    def __compute_cost(self, AL, Y):
86
        m = Y.shape[1]
87
        cost = -np.sum(Y*np.log(AL) + (1-Y)*np.log(1-AL)) / m
88
        return cost
89
90
    # 损失函数
91
    def cost_function(self, X, Y):
92
        assert (self.input_size == X.shape[0])
93
        AL, _ = self.__forward_propagation(X)
94
        return self.__compute_cost(AL, Y)
95
96
    # S激活函数反向传播
97
    def sigmoid_backward(self, dA, Z):
98
        s = sigmoid(Z)
99
        dZ = dA * s*(1-s)
100
        return dZ
101
102
    # RELU激活函数反向传播
103
    def relu_backward(self, dA, Z):
104
        dZ = np.array(dA, copy=True)
105
        dZ[Z <= 0] = 0
106
        return dZ
107
108
    # Leaky RULE激活函数反向传播
109
    def leaky_relu_backward(self, dA, Z):
110
        dZ = np.array(dA, copy=True)
111
        dZ[Z <= 0] = 0.01
112
        return dZ
113
114
    # tanh激活函数反向传播
115
    def tanh_backward(self, dA, Z):
116
        s = np.tanh(Z)
117
        dZ = 1 - s*s
118
        return dZ
119
120
    # 线性激活函数反向传播
121
    def __linear_backward(self, dZ, A_prev, W):
122
        m = A_prev.shape[1]
123
        dW = np.dot(dZ, A_prev.T) / m
124
        db = np.sum(dZ, axis=1, keepdims=True) / m
125
        dA_prev = np.dot(W.T, dZ)
126
        return dA_prev, dW, db
127
128
    # 激活函数反向传播
129
    def __activation_backward(self, dA, Z, activation):
130
        assert (dA.shape == Z.shape)
131
        if activation == 'sigmoid':
132
            dZ = self.sigmoid_backward(dA, Z)
133
        if activation == 'relu':
134
            dZ = self.relu_backward(dA, Z)
135
        if activation == 'leaky_relu':
136
            dZ = self.leaky_relu_backward(dA, Z)
137
        if activation == 'tanh':
138
            dZ = self.tanh_backward(dA, Z)
139
        return dZ
140
141
    # 反向传播
142
    def __backward_propagation(self, caches, Y):
143
        m = Y.shape[1]
144
        L = self.__num_layers
145
        grads = {}
146
        AL, A_prev = caches[L-1]['A'], caches[L-2]['A']
147
        grads['dZ'+str(L-1)] = AL - Y
148
        grads['dA'+str(L-2)], grads['dW'+str(L-1)], grads['db'+str(L-1)] = self.__linear_backward(grads['dZ'+str(L-1)], A_prev, self.parameters['W'+str(L-1)])
149
        for l in reversed(range(1, L-1)):
150
            grads['dZ'+str(l)] = self.__activation_backward(grads['dA'+str(l)], caches[l]['Z'], self.activations[l-1])
151
            A_prev = caches[l-1]['A']
152
            grads['dA'+str(l-1)], grads['dW'+str(l)], grads['db'+str(l)] = self.__linear_backward(grads['dZ'+str(l)], A_prev, self.parameters['W'+str(l)])
153
        return grads
154
155
    # 更新参数
156
    def __update_parameters(self, grads, learning_rate):
157
        for l in range(1, self.__num_layers):
158
            self.parameters['W'+str(l)] -= learning_rate * grads['dW'+str(l)]
159
            self.parameters['b'+str(l)] -= learning_rate * grads['db'+str(l)]
160
161
    # 拟合
162
    def fit(self, X, Y, num_iterations, learning_rate, print_cost=False, print_num=100):
163
        for i in range(num_iterations):
164
            AL, caches = self.__forward_propagation(X)
165
            cost = self.__compute_cost(AL, Y)
166
            grads = self.__backward_propagation(caches, Y)
167
            self.__update_parameters(grads, learning_rate)
168
            if i % print_num == 0 and print_cost:
169
                    print ("Cost after iteration %i: %f" %(i, cost))
170
        return self
171
172
    # 预测概率
173
    def predict_prob(self, X):
174
        A, _ = self.__forward_propagation(X)
175
        return A
176
177
    # 预测分类
178
    def predict(self, X, threshold=0.5):
179
        pred_prob = self.predict_prob(X)
180
        threshold_func = np.vectorize(lambda x: 1 if x > threshold else 0)
181
        Y_prediction = threshold_func(pred_prob)
182
        return Y_prediction
183
184
    # 精度
185
    def accuracy_score(self, X, Y):
186
        pred = self.predict(X)
187
        return len(Y[pred == Y]) / Y.shape[1]
188
189
190
# 加载数据
191
np.random.seed(1)
192
train_x_orig, train_y, test_x_orig, test_y, classes = load_data()
193
m_train = train_x_orig.shape[0]
194
num_px = train_x_orig.shape[1]
195
m_test = test_x_orig.shape[0]
196
print ("Number of training examples: " + str(m_train))
197
print ("Number of testing examples: " + str(m_test))
198
print ("Each image is of size: (" + str(num_px) + ", " + str(num_px) + ", 3)")
199
print ("train_x_orig shape: " + str(train_x_orig.shape))
200
print ("train_y shape: " + str(train_y.shape))
201
print ("test_x_orig shape: " + str(test_x_orig.shape))
202
print ("test_y shape: " + str(test_y.shape))
203
204
# 调整训练集与测试集数据
205
train_x_flatten = train_x_orig.reshape(train_x_orig.shape[0], -1).T
206
test_x_flatten = test_x_orig.reshape(test_x_orig.shape[0], -1).T
207
train_x = train_x_flatten/255.
208
test_x = test_x_flatten/255.
209
print ("train_x's shape: " + str(train_x.shape))
210
print ("test_x's shape: " + str(test_x.shape))
211
212
# 设置参数
213
layers_dims = (12288, 20, 7, 5, 1)
214
activations = ['relu', 'relu', 'relu','sigmoid']
215
num_iter = 2500
216
learning_rate = 0.0075
217
# 开始训练
218
clf = DeepNeuralNetwork(layers_dims, activations).fit(train_x, train_y, num_iter, learning_rate, True, 100)
219
print('train accuracy: {:.2f}%'.format(clf.accuracy_score(train_x, train_y)*100))
220
print('test accuracy: {:.2f}%'.format(clf.accuracy_score(test_x, test_y)*100))

训练结果

1
Cost after iteration 0: 0.771749
2
Cost after iteration 100: 0.672053
3
Cost after iteration 200: 0.648263
4
Cost after iteration 300: 0.611507
5
Cost after iteration 400: 0.567047
6
Cost after iteration 500: 0.540138
7
Cost after iteration 600: 0.527930
8
Cost after iteration 700: 0.465477
9
Cost after iteration 800: 0.369126
10
Cost after iteration 900: 0.391747
11
Cost after iteration 1000: 0.315187
12
Cost after iteration 1100: 0.272700
13
Cost after iteration 1200: 0.237419
14
Cost after iteration 1300: 0.199601
15
Cost after iteration 1400: 0.189263
16
Cost after iteration 1500: 0.161189
17
Cost after iteration 1600: 0.148214
18
Cost after iteration 1700: 0.137775
19
Cost after iteration 1800: 0.129740
20
Cost after iteration 1900: 0.121225
21
Cost after iteration 2000: 0.113821
22
Cost after iteration 2100: 0.107839
23
Cost after iteration 2200: 0.102855
24
Cost after iteration 2300: 0.100897
25
Cost after iteration 2400: 0.092878
26
train accuracy: 98.56%
27
test accuracy: 80.00%