|
| 1 | +# -*- coding: utf-8 -*- |
| 2 | +# By: Eastmount CSDN 2021-04-01 |
| 3 | +import os |
| 4 | +import cv2 |
| 5 | +import numpy as np |
| 6 | +from sklearn.model_selection import train_test_split |
| 7 | +from sklearn.metrics import confusion_matrix, classification_report |
| 8 | + |
| 9 | +#---------------------------------------------------------------------------------- |
| 10 | +# 第一步 图像读取及转换为像素直方图 |
| 11 | +#---------------------------------------------------------------------------------- |
| 12 | + |
| 13 | +X = [] |
| 14 | +Y = [] |
| 15 | + |
| 16 | +for i in range(0, 10): |
| 17 | + #遍历文件夹,读取图片 |
| 18 | + for f in os.listdir("photo/%s" % i): |
| 19 | + #获取图像像素 |
| 20 | + Images = cv2.imread("photo/%s/%s" % (i, f)) |
| 21 | + image=cv2.resize(Images,(256,256),interpolation=cv2.INTER_CUBIC) |
| 22 | + hist = cv2.calcHist([image], [0,1], None, [256,256], [0.0,255.0,0.0,255.0]) |
| 23 | + X.append((hist/255).flatten()) |
| 24 | + Y.append(i) |
| 25 | + |
| 26 | +X = np.array(X) |
| 27 | +Y = np.array(Y) |
| 28 | + |
| 29 | +#切分训练集和测试集 |
| 30 | +X_train, X_test, y_train, y_test = train_test_split(X, Y, |
| 31 | + test_size=0.3, random_state=1) |
| 32 | + |
| 33 | +#---------------------------------------------------------------------------------- |
| 34 | +# 第二步 定义神经网络函数 |
| 35 | +#---------------------------------------------------------------------------------- |
| 36 | + |
| 37 | +from sklearn.preprocessing import LabelBinarizer |
| 38 | +import random |
| 39 | + |
| 40 | +def logistic(x): |
| 41 | + return 1 / (1 + np.exp(-x)) |
| 42 | + |
| 43 | +def logistic_derivative(x): |
| 44 | + return logistic(x) * (1 - logistic(x)) |
| 45 | + |
| 46 | +class NeuralNetwork: |
| 47 | + def predict(self, x): |
| 48 | + for b, w in zip(self.biases, self.weights): |
| 49 | + # 计算权重相加再加上偏向的结果 |
| 50 | + z = np.dot(x, w) + b |
| 51 | + # 计算输出值 |
| 52 | + x = self.activation(z) |
| 53 | + return self.classes_[np.argmax(x, axis=1)] |
| 54 | + |
| 55 | +class BP(NeuralNetwork): |
| 56 | + |
| 57 | + def __init__(self,layers,batch): |
| 58 | + |
| 59 | + self.layers = layers |
| 60 | + self.batch = batch |
| 61 | + self.activation = logistic |
| 62 | + self.activation_deriv = logistic_derivative |
| 63 | + |
| 64 | + self.num_layers = len(layers) |
| 65 | + self.biases = [np.random.randn(x) for x in layers[1:]] |
| 66 | + self.weights = [np.random.randn(x, y) for x, y in zip(layers[:-1], layers[1:])] |
| 67 | + |
| 68 | + def fit(self, X, y, learning_rate=0.1, epochs=1): |
| 69 | + |
| 70 | + labelbin = LabelBinarizer() |
| 71 | + y = labelbin.fit_transform(y) |
| 72 | + self.classes_ = labelbin.classes_ |
| 73 | + training_data = [(x,y) for x, y in zip(X, y)] |
| 74 | + n = len(training_data) |
| 75 | + for k in range(epochs): |
| 76 | + #每次迭代都循环一次训练 |
| 77 | + #训练集乱序 |
| 78 | + random.shuffle(training_data) |
| 79 | + batches = [training_data[k:k+self.batch] for k in range(0, n, self.batch)] |
| 80 | + #批量梯度下降 |
| 81 | + for mini_batch in batches: |
| 82 | + x = [] |
| 83 | + y = [] |
| 84 | + for a,b in mini_batch: |
| 85 | + x.append(a) |
| 86 | + y.append(b) |
| 87 | + activations = [np.array(x)] |
| 88 | + #向前一层一层的走 |
| 89 | + for b, w in zip(self.biases, self.weights): |
| 90 | + #计算激活函数的参数,计算公式:权重.dot(输入)+偏向 |
| 91 | + z = np.dot(activations[-1],w)+b |
| 92 | + #计算输出值 |
| 93 | + output = self.activation(z) |
| 94 | + #将本次输出放进输入列表 后面更新权重的时候备用 |
| 95 | + activations.append(output) |
| 96 | + #计算误差值 |
| 97 | + error = activations[-1]-np.array(y) |
| 98 | + #计算输出层误差率 |
| 99 | + deltas = [error * self.activation_deriv(activations[-1])] |
| 100 | + |
| 101 | + #循环计算隐藏层的误差率 从倒数第2层开始 |
| 102 | + for l in range(self.num_layers-2, 0, -1): |
| 103 | + deltas.append(self.activation_deriv(activations[l]) * np.dot(deltas[-1],self.weights[l].T)) |
| 104 | + |
| 105 | + #将各层误差率顺序颠倒 准备逐层更新权重和偏向 |
| 106 | + deltas.reverse() |
| 107 | + #更新权重和偏向 |
| 108 | + for j in range(self.num_layers-1): |
| 109 | + # 权重的增长量 计算公式为: 增长量 = 学习率 × (错误率.dot(输出值)) |
| 110 | + delta = learning_rate/self.batch*((np.atleast_2d(activations[j].sum(axis=0)).T).dot(np.atleast_2d(deltas[j].sum(axis=0)))) |
| 111 | + #更新权重 |
| 112 | + self.weights[j] -= delta |
| 113 | + #偏向增加量 计算公式为: 学习率 × 错误率 |
| 114 | + delta = learning_rate/self.batch * deltas[j].sum(axis=0) |
| 115 | + #更新偏向 |
| 116 | + self.biases[j] -= delta |
| 117 | + return self |
| 118 | + |
| 119 | +#---------------------------------------------------------------------------------- |
| 120 | +# 第三步 基于神经网络的图像分类处理 |
| 121 | +#---------------------------------------------------------------------------------- |
| 122 | + |
| 123 | +clf = BP([X_train.shape[1],10],10).fit(X_train,y_train,epochs=100) |
| 124 | +predictions_labels = clf.predict(X_test) |
| 125 | +print('预测结果:') |
| 126 | +print(predictions_labels) |
| 127 | +print('算法评价:') |
| 128 | +print(classification_report(y_test, predictions_labels)) |
0 commit comments