最近,我在网上了解了反向传播,并试图实现它。我还不确定我是否正确。我很困惑,很想再看一双关于这个代码的眼睛。请帮助我理解如何改进这一点,如果这是正确的。
"""
Artificial Neural Network
"""
import numpy as np
def sigmoid(x, derivative=False):
output = 1 / (1 + np.exp(-x))
if derivative:
return output * (1 - output)
return output
def tanh(x, derivative=False):
output = 2 * sigmoid(2 * x) - 1
if derivative:
return 1 - output ** 2
return output
class Layer:
def __init__(self, num_input, num_output, activation_fn=tanh):
# num_rows = num_input, num_cols = num_output
self.weights = activation_fn(np.random.rand(num_input, num_output))
self.bias = activation_fn(np.random.rand(1, num_output))
self.activation_fn = activation_fn
self.raw = None
self.activated = None
self.input_data = None
def __str__(self):
return "Weights:\n" + str(self.weights) + "\nBias:\n" + str(self.bias)
def output(self, x):
self.input_data = x
self.raw = np.dot(x, self.weights) + self.bias
self.activated = self.activation_fn(self.raw)
return self.activated
def output_der(self):
return self.activation_fn(self.activated, derivative=True)
class NeuralNetwork:
def __init__(self, layers, eta=0.1):
if len(layers) < 2:
raise Exception("Layers needs to have input and output")
self.layers = self.init_layers(layers)
self.eta = eta
def __str__(self):
s = ""
for i, l in enumerate(self.layers):
s += "Layer {}.\n{}\n\n".format(i, str(l))
s += "--------------"
return s
def init_layers(self, layers):
ann = []
i = 0
while i < len(layers) - 1:
ann.append(Layer(layers[i], layers[i + 1]))
i += 1
return ann
def train(self, dataset, times=45):
# item[0] = input
# item[1] = label
# backpropagation is an online algorithm (one example at a time)
for i in range(times):
error = 0
output = 0
for item in dataset:
output = self.forward(np.array(item[0]))
# loss_at_output_layer = -(label - output)
self.backward(output - item[1])
error += (item[1] - output) ** 2
print(error)
def hot_encode(self, output):
top = max(output)
for i in range(len(output)):
output[i] = 0 if output[i] != top else 1
return output
def test(self, dataset):
accuracy = 0
for item in dataset:
output = self.forward(np.array(item[0]))
if np.array_equal(self.hot_encode(output[0]), item[1]):
accuracy += 1
print("Accuracy: {}\n".format(accuracy / len(dataset)))
def forward(self, item):
x = item
for l in self.layers:
x = l.output(x)
return x
def backward(self, loss):
# delta_i = error * Δoutput_i
deltas = []
for l in reversed(self.layers):
deltas.append(np.multiply(loss, l.output_der()))
loss = np.dot(deltas[-1], l.weights.T)
l.weights -= self.eta * np.multiply(deltas[-1], l.weights)
l.bias -= self.eta * deltas[-1]
#---------------------------------------------------------------------#
"""
Driver Code
"""
def normalize(data):
return (2 * (data - min(data)) / (max(data) - min(data))) - 1
def get_dataset(filename):
with open(filename, "r") as f:
raw = {}
for line in f:
line_data = line.split(",")
feature = normalize(np.array(list(map(float, line_data[:-1]))))
if line_data[-1] in raw:
raw[line_data[-1]].append(feature)
else:
raw[line_data[-1]] = [feature]
hot_encoding = {}
for i, label in enumerate(raw):
hot_encoding[label] = np.zeros(len(raw))
hot_encoding[label][i] = 1
dataset = []
for label in raw:
for feature in raw[label]:
dataset.append([feature, hot_encoding[label]])
return dataset
if __name__ == "__main__":
classifier = NeuralNetwork([4, 3], eta=0.01)
print("{}\n".format(classifier))
dataset = get_dataset("./iris.data")
np.random.shuffle(dataset)
print(dataset)
split_ratio = int(2 * len(dataset) / 3)
classifier.train(dataset[:split_ratio], times=50)
classifier.test(dataset[split_ratio:])
print("{}\n".format(classifier))我正试图在虹膜数据集上测试它,但它并不收敛。我尝试了以下架构:
请帮助我识别如何改进算法、表示和代码质量。请让我知道如何改进这个问题,以帮助您更好地回答这个问题。非常感谢!
发布于 2019-09-08 19:45:12
首先,我不是代码审查员。不过,您的代码似乎没有问题。在编写Python脚本时,有一些基本的编码约定,比如变量命名、注释、docstring等等,我没有对它们进行讨论,因为我正在学习它,您可以找到它这里。
有几个基本的ANN不能正确地收敛,例如:
Neuron类的东西。您还可以应用一些已经内置的模块来执行此操作,例如在本例中使用KNN,我非常肯定您知道:
from sklearn import neighbors, datasets, preprocessing
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
from sklearn.metrics import classification_report
from sklearn.metrics import confusion_matrix
iris = datasets.load_iris()
X, y = iris.data[:, :], iris.target
Xtrain, Xtest, y_train, y_test = train_test_split(X, y)
scaler = preprocessing.StandardScaler().fit(Xtrain)
Xtrain = scaler.transform(Xtrain)
Xtest = scaler.transform(Xtest)
knn = neighbors.KNeighborsClassifier(n_neighbors=4)
knn.fit(Xtrain, y_train)
y_pred = knn.predict(Xtest)
print(accuracy_score(y_test, y_pred))
print(classification_report(y_test, y_pred))
print(confusion_matrix(y_test, y_pred))0.8947368421052632
precision recall f1-score support
0 1.00 1.00 1.00 13
1 0.79 0.92 0.85 12
2 0.91 0.77 0.83 13
accuracy 0.89 38
macro avg 0.90 0.90 0.89 38
weighted avg 0.90 0.89 0.89 38
[[13 0 0]
[ 0 11 1]
[ 0 3 10]]我认为你正试图从零开始实施ANN,这是很好的。
https://codereview.stackexchange.com/questions/227684
复制相似问题