Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import numpy as np
- import csv
- import Circle_data
- import matplotlib.pyplot as plt
- class Data(): #這個類別協助我們把資料轉成向量以及上好標籤
- def __init__(self, x, z):
- self.x = self.setX(x)
- self.z = self.setZ(z)
- def setX(self, x):
- return np.array([x]).T
- def setZ(self, z):
- return np.array([z]).T
- def readData(): #這個函數用來讀取資料
- data = []
- with open("output.csv", newline = "") as csvfile:
- rows = csv.DictReader(csvfile)
- for row in rows:
- x = [float(row['x1']), float(row['x2'])]
- z = [float(row['z'])]
- data.append(Data(x, z))
- return data
- def f(x, function_name = 'ReLU'):
- if function_name == 'ReLU':
- return np.maximum(x, 0)
- elif function_name == 'tanh':
- return np.tanh(x)
- elif function_name == 'sigmoid':
- return 1 / (1 + np.exp(-x))
- def df(x, Hidden_nodes, function_name = 'ReLU'):
- if function_name == 'ReLU':
- return np.eye(Hidden_nodes, dtype = 'float')*(np.where(x > 0, 1, 0))
- elif function_name == 'tanh':
- return np.eye(Hidden_nodes, dtype = 'float')*(1 - f(x, function_name)*f(x, function_name))
- elif function_name == 'sigmoid':
- return np.eye(Hidden_nodes, dtype = 'float')*(f(x, function_name)*(1 - f(x, function_name)))
- def loss(N, Layer, data, loss_name ='MSE'):
- if loss_name == 'MSE':
- result = 0
- for i in range(N):
- result = result + (Layer[2][i] - data[i].z)**2
- return result / (2*N)
- def forward(W1, W2, b, N, data, function_name = 'ReLU'): #向前傳播
- Layer1_1 = []
- Layer1_2 = []
- output = []
- Layer = []
- for i in range(N):
- Layer1_1.append(W1.dot(data[i].x)+b) #計算每一層的值,並存取下來
- Layer1_2.append(f(Layer1_1[i], function_name))
- output.append(W2.dot(Layer1_2[i]))
- Layer.append(Layer1_1)
- Layer.append(Layer1_2)
- Layer.append(output)
- return Layer
- def backward(W2, N, Layer, data, Hidden_nodes, function_name = 'ReLU'): #反向傳播
- dW2 = np.zeros((1, Hidden_nodes)) #計算W2的梯度
- for i in range(N):
- dW2 = dW2 + (Layer[2][i] - data[i].z)*(Layer[1][i].T)
- dW2 = dW2 / N
- dW1 = np.zeros((Hidden_nodes, 2)) #計算W1和b的梯度
- db = np.zeros((Hidden_nodes, 1))
- for i in range(N):
- temp = (Layer[2][i] - data[i].z)*W2.dot(df(Layer[0][i], Hidden_nodes, function_name))
- db = db + temp.T
- dW1 = dW1 + np.kron(temp.T, data[i].x.T)
- dW1 = dW1 / N
- db = db / N
- return dW1, dW2, db
- def Train(W1, W2, b, data, Hidden_nodes, N, learning_rate = 0.3, beta = 0.1, gamma = 0.9, beta1 = 0.9, beta2 = 0.999, Method = 'Adam', function_name = 'ReLU', loss_name ='MSE', train_size = 20000):
- TOL=1e-7
- k = 1
- Layer = forward(W1, W2, b, N, data)
- best_result = 0
- mW1 = sW1 = vW1 = np.zeros(W1.shape)
- mW2 = sW2 = vW2 = np.zeros(W2.shape)
- mb = sb = vb = np.zeros(b.shape)
- train = []
- test = []
- G = [[], [], []]
- dG = [np.zeros(W1.shape), np.zeros(W2.shape), np.zeros(b.shape)]
- y = []
- for i in range(train_size):
- train.append(data[i])
- for i in range(N-train_size):
- test.append(data[train_size+i])
- Layer = forward(W1, W2, b, train_size, data, function_name = 'ReLU')
- while k <= 200:
- dW1, dW2, db = backward(W2, train_size, Layer, train, Hidden_nodes, function_name = 'ReLU')
- if Method == 'GradientDescent':
- W1 = W1 - learning_rate*dW1
- W2 = W2 - learning_rate*dW2
- b = b - learning_rate*db
- elif Method == 'Momentum':
- mW1 = beta*dW1 + gamma*mW1
- mW2 = beta*dW2 + gamma*mW2
- mb = beta*db + gamma*mb
- W1 = W1 - learning_rate*mW1
- W2 = W2 - learning_rate*mW2
- b = b - learning_rate*mb
- elif Method == 'Adagrad':
- G[0].append(dW1)
- G[1].append(dW2)
- G[2].append(db)
- for i in range(k):
- dG[0] += G[0][i]**2
- dG[1] += G[1][i]**2
- dG[2] += G[2][i]**2
- dG[0] = dG[0]**(1/2)
- dG[1] = dG[1]**(1/2)
- dG[2] = dG[2]**(1/2)
- W1 = W1 - (learning_rate/(dG[0] + TOL))*dW1
- W2 = W2 - (learning_rate/(dG[1] + TOL))*dW2
- b = b - (learning_rate/(dG[2] + TOL))*db
- elif Method == 'RMSProp':
- G[0].append(dW1)
- G[1].append(dW2)
- G[2].append(db)
- for i in range(k):
- dG[0] += G[0][i]**2
- dG[1] += G[1][i]**2
- dG[2] += G[2][i]**2
- dG[0] = (1/k)*dG[0]
- dG[1] = (1/k)*dG[1]
- dG[2] = (1/k)*dG[2]
- dG[0] = dG[0]**(1/2)
- dG[1] = dG[1]**(1/2)
- dG[2] = dG[2]**(1/2)
- W1 = W1 - (learning_rate/(dG[0] + TOL))*dW1
- W2 = W2 - (learning_rate/(dG[1] + TOL))*dW2
- b = b - (learning_rate/(dG[2] + TOL))*db
- elif Method == 'Adam':
- vW1 = beta1*vW1 + (1 - beta1)*dW1
- vW2 = beta1*vW2 + (1 - beta1)*dW2
- vb = beta1*vb + (1 - beta1)*db
- sW1 = beta2*sW1 + (1 - beta2)*dW1*dW1
- sW2 = beta2*sW2 + (1 - beta2)*dW2*dW2
- sb = beta2*sb + (1 - beta2)*db*db
- vW1_hat = vW1/(1 - beta1**k)
- vW2_hat = vW2/(1 - beta1**k)
- vb_hat = vb/(1 - beta1**k)
- sW1_hat = sW1/(1 - beta2**k)
- sW2_hat = sW2/(1 - beta2**k)
- sb_hat = sb/(1 - beta2**k)
- new_dW1 = learning_rate*vW1_hat/(np.sqrt(sW1_hat)+TOL)
- new_dW2 = learning_rate*vW2_hat/(np.sqrt(sW2_hat)+TOL)
- new_db = learning_rate*vb_hat/(np.sqrt(sb_hat)+TOL)
- W1 = W1 - new_dW1
- W2 = W2 - new_dW2
- b = b - new_db
- Layer = forward(W1, W2, b, train_size, train, function_name = 'ReLU')
- result = ANN(W1, W2, b, test, function_name = 'ReLU')
- y.append(float(loss(train_size, Layer, train, loss_name ='MSE')))
- print(k)
- print(y[k-1])
- if result[1] > best_result:
- best_result = result[1]
- bestW1 = W1
- bestW2 = W2
- bestb = b
- k = k + 1
- return bestW1, bestW2, bestb, y
- def ANN(W1, W2, b, data, function_name = 'ReLU'):
- M = len(data)
- output = forward(W1, W2, b, M, data, function_name)
- ans = []
- correct = 0
- for i in range(M):
- if output[2][i] < 0:
- ans.append(-1)
- else:
- ans.append(1)
- if ans[i] == data[i].z:
- correct = correct + 1
- return [ans, correct / M]
- def GenerateWeight(Hidden_nodes):
- W1 = np.random.rand(Hidden_nodes, 2) #權重矩陣W1和W2
- W2 = np.random.rand(1,Hidden_nodes)
- b = np.random.rand(Hidden_nodes,1) #偏置向量b
- return W1, W2, b
- def GenerateTestData(M):
- temp = []
- test_data = []
- for i in range(M):
- r = np.random.randint(0, 2)
- if r == 1:
- temp.append(Circle_data.Data("blue"))
- else:
- temp.append(Circle_data.Data("red"))
- test_data.append(Data(temp[i].x, temp[i].z))
- return test_data
- def main():
- data = readData() #把資料讀進來
- N = len(data) #取得資料的個數
- Hidden_nodes = 4
- t = np.arange(100)
- """
- learning_rate = 0.3
- beta = 0.1
- gamma = 0.9
- beta1 = 0.9
- beta2 = 0.999
- Method = 'Adam'
- function_name = 'ReLU'
- loss_name ='MSE'
- train_size = 20000
- """
- W1, W2, b = GenerateWeight(Hidden_nodes)
- W1_1, W2_1, b_1, y_1 = Train(W1, W2, b, data, Hidden_nodes, N, learning_rate = 0.01, Method = 'GradientDescent')
- W1_2, W2_2, b_2, y_2 = Train(W1, W2, b, data, Hidden_nodes, N, learning_rate = 0.01, Method = 'Momentum')
- W1_3, W2_3, b_3, y_3 = Train(W1, W2, b, data, Hidden_nodes, N, learning_rate = 0.01, Method = 'Adagrad')
- W1_4, W2_4, b_4, y_4 = Train(W1, W2, b, data, Hidden_nodes, N, learning_rate = 0.01, Method = 'RMSProp')
- W1_5, W2_5, b_5, y_5 = Train(W1, W2, b, data, Hidden_nodes, N, learning_rate = 0.01, Method = 'Adam')
- plt.plot(t, y_1, 'b-', t, y_2, 'r-', t, y_3, 'g-', t, y_4, 'k-', t, y_5, 'y-')
- plt.show()
- plt.savefig('plot1.png')
- M = 1000
- test_data = GenerateTestData(M)
- result = ANN(W1_1, W2_1, b_1, test_data)
- print("命中率=",100*result[1],'%')
- result = ANN(W1_2, W2_2, b_2, test_data)
- print("命中率=",100*result[1],'%')
- result = ANN(W1_3, W2_3, b_3, test_data)
- print("命中率=",100*result[1],'%')
- result = ANN(W1_4, W2_4, b_4, test_data)
- print("命中率=",100*result[1],'%')
- result = ANN(W1_5, W2_5, b_5, test_data)
- print("命中率=",100*result[1],'%')
- if __name__ == "__main__":
- main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement