Data fusion neural network model Data dataset image classification

Use neural network model for image classification (data set Data)

Design your own neural network, or use an existing network to train on training data

You are not allowed to use a trained model. You need to train it yourself, and then test the trained model on the test data.

Need to adjust parameters by yourself

data data set, three label data (horse, airplane, car)

import warnings
warnings.filterwarnings("ignore")

import datetime

import matplotlib.pyplot as plt

import time

starttime = datetime.datetime.now()

import numpy as np
#from sklearn.cross_validation import train_test_split
from sklearn.model_selection import train_test_split

from sklearn.metrics import confusion_matrix, classification_report
#error:UndefinedMetricWarning:
# Precision and F-score are ill-defined and being set to 0.0 in labels with no predicted samples.
# Use `zero_division` parameter to control this behavior.
#  _warn_prf(average, modifier, msg_start, len(result))
#https://blog.csdn.net/qq_43391414/article/details/120543028
import os
import cv2

X = []
Y = []

width = 256
height = 256
# for i in range(0, 10):
for i in range(0+1, 3+1):
    # 遍历文件夹,读取图片
    # for f in os.listdir("./photo/%s" % i):
    # for f in os.listdir("./data/data/train"):
    # for f in os.listdir("./test2"):
    for f in os.listdir("./data/data/train/%s" %i):
    # for f in os.listdir("./data/data/train"):
        # 打开一张图片并灰度化
        # Images = cv2.imread("./photo/%s/%s" % (i, f))
        # https: // blog.csdn.net / weixin_44015965 / article / details / 109547129
        # Images = cv2.imread("./data/data/train/%s" % f)
        Images = cv2.imread("./data/data/train/%s/%s" % (i,f))
        #图片放缩
        image = cv2.resize(Images, (256, 256), interpolation=cv2.INTER_CUBIC)
        # cv2.calcHist()函数的作用:
        # 通过直方图可以很好的对整幅图像的灰度分布有一个整体的了解,直方图的x轴是灰度值(0
        # ~255),y轴是图片中具有同一个灰度值的点的数目。而calcHist()函数则可以帮助我们统计一幅图像的直方图
        hist = cv2.calcHist([image], [0, 1], None, [256, 256], [0.0, 255.0, 0.0, 255.0])
        X.append((hist / 255).flatten())
        Y.append(i)
X = np.array(X)
Y = np.array(Y)
# 切分训练集和测试集
# X_train, X_test, y_train, y_test = train_test_split(X, Y, test_size=0.3, random_state=1)
X_train, X_test, y_train, y_test = train_test_split(X, Y, test_size=300, random_state=1)
# test_size	若在0~1之间,为测试集样本数目与原始样本数目之比;若为整数,则是测试集样本的数目。
# random_state	随机数种子
# X_train	划分出的训练集数据(返回值)
# X_test	划分出的测试集数据(返回值)
# y_train	划分出的训练集标签(返回值)
# y_test	划分出的测试集标签(返回值)
# X	待划分的样本特征集合
# y	待划分的样本标签
from sklearn.preprocessing import LabelBinarizer
import random


def logistic(x):
    return 1 / (1 + np.exp(-x))


def logistic_derivative(x):
    return logistic(x) * (1 - logistic(x))


class NeuralNetwork:

    def predict(self, x):
        # w , b
        for b, w in zip(self.biases, self.weights):
            # 计算权重相加再加上偏向的结果
            z = np.dot(x, w) + b
            # 计算输出值
            x = self.activation(z)
        return self.classes_[np.argmax(x, axis=1)]

# BP 算法是一个迭代算法,它的基本思想为:
# (1) 先计算每一层的状态和激活值,直到最后一层(即信号是前向传播的);
# (2) 计算每一层的误差,误差的计算过程是从最后一层向前推进的(这就是反向传播算法名字的由来);
# (3) 更新参数(目标是误差变小),迭代前面两个步骤,直到满足停止准则(比如相邻两次迭代的误差的差别很小)。
class BP(NeuralNetwork):

    def __init__(self, layers, batch):

        # 层
        self.layers = layers
        # 批处理
        self.batch = batch
        # 流
        self.activation = logistic
        #
        self.activation_deriv = logistic_derivative
        # length
        self.num_layers = len(layers)
        # 偏差 b
        self.biases = [np.random.randn(x) for x in layers[1:]]
        # 权重 w
        self.weights = [np.random.randn(x, y) for x, y in zip(layers[:-1], layers[1:])]

    def fit(self, X, y, learning_rate=0.2, epochs=1):
        print(learning_rate)

        # class sklearn.preprocessing.LabelBinarizer(neg_label=0, pos_label=1, sparse_output=False)
        labelbin = LabelBinarizer()
          # LabelBinarizer()
          # 是sklearn.preprocessing中的一个函数,通过这个函数可以实现机器学习中国对图像标签的独热编码。
          # 独热编码是一种二进制编码,通俗的讲独热编码主要满足以下几个条件:
          #
          # 图像有n类,则编码长度为n
          # 对第i类编码,只有第i位置1,其余为0(1 ≤ i ≤ n
        y = labelbin.fit_transform(y)
        # fit_transform(self, y)  设定或者初始化二进制分类器并开始对y进行转换
        self.classes_ = labelbin.classes_

        training_data = [(x, y) for x, y in zip(X, y)]
        n = len(training_data)
        print(n)
        for k in range(epochs):
            t = time.localtime()
            print(k,t)
            # 每次迭代都循环一次训练
            random.shuffle(training_data)
            # 搅乱训练集,让其排序顺序发生变化
            # print(self.batch)
            batches = [training_data[k:k + self.batch] for k in range(0, n, self.batch)]
            # print(batches)
            # 批量梯度下降
            for mini_batch in batches:
                x = []
                y = []
                for a, b in mini_batch:
                    x.append(a)
                    y.append(b)
                activations = [np.array(x)]
                # 向前一层一层的走
                for b, w in zip(self.biases, self.weights):
                    # 计算激活函数的参数,计算公式:权重.dot(输入)+偏向
                    z = np.dot(activations[-1], w) + b
                    # 计算输出值
                    output = self.activation(z)
                    # 将本次输出放进输入列表,后面更新权重的时候备用
                    activations.append(output)
                # 计算误差值
                error = activations[-1] - np.array(y)
                # 计算输出层误差率
                deltas = [error * self.activation_deriv(activations[-1])]

                # 循环计算隐藏层的误差率,从倒数第2层开始
                for l in range(self.num_layers - 2, 0, -1):
                    deltas.append(self.activation_deriv(activations[l]) * np.dot(deltas[-1], self.weights[l].T))

                # 将各层误差率顺序颠倒,准备逐层更新权重和偏向
                deltas.reverse()
                # 更新权重和偏向
                for j in range(self.num_layers - 1):
                    # 权重的增长量,计算公式,增长量 = 学习率 * (错误率.dot(输出值)),单个训练数据的误差
                    delta = learning_rate / self.batch * (
                        (np.atleast_2d(activations[j].sum(axis=0)).T).dot(np.atleast_2d(deltas[j].sum(axis=0))))
                    # 更新权重
                    self.weights[j] -= delta
                    # 偏向增加量,计算公式:学习率 * 错误率
                    delta = learning_rate / self.batch * deltas[j].sum(axis=0)
                    # 更新偏向
                    self.biases[j] -= delta
        return self


# clf0 = BP([X_train.shape[1], 10], 10).fit(X_train, y_train, epochs=100)

clf0 = BP([X_train.shape[1], 3], 4).fit(X_train, y_train, epochs=100)
# def fit(self, X, y, learning_rate=0.1, epochs=1):
        # def fit(self, X, y, learning_rate=0.2, epochs=10000):
        # 设定epochs为循环的最高次数,即到最高时就直接结束循环 X = np.a...

predictions_labels = clf0.predict(X_test)
print(confusion_matrix(y_test, predictions_labels))
print(classification_report(y_test, predictions_labels))
# classification_report(
# y_true,
# y_pred,
# labels=None,
# target_names=None,
# sample_weight=None,
# digits=2,
# output_dict=False,
# zero_division=“warn”
# )
#
# 参数	描述
# y_true	真实值 ,一维数组形式(也可以是列表元组之类的)
# y_pred	预测值,一维数组形式(也可以是列表元组之类的)
# labels	标签索引列表,可选参数,数组形式
# target_names	与标签匹配的名称,可选参数,数组形式
# sample_weight	样本权重,数组形式
# digits	格式化输出浮点值的位数。默认为2。当“output_dict”为“True”时,这将被忽略,并且返回的值不会四舍五入。
# output_dict	是否输出字典。默认为False,如果为True则输出结果形式为字典。
# zero_division	设置存在零除法时返回的值。默认为warn。如果设置为“warn”,这相当于0,但也会引发警告。

endtime = datetime.datetime.now()
print(endtime - starttime)

Guess you like

Origin blog.csdn.net/m0_54070377/article/details/131076019