CV(7)--神经网络训练

发布于:2025-02-11 ⋅ 阅读:(33) ⋅ 点赞:(0)

前言

仅记录学习过程,有问题欢迎讨论

什么是神经网络:

  • 神经网络是一种模拟人脑神经元工作原理的算法,它由多个神经元组成,每个神经元都接受输入,通过计算产生输出,并将输出传递给其他神经元。
  • 神经网络的基本结构包括输入层、隐藏层和输出层。输入层接受外部输入,隐藏层对输入进行计算和转换,输出层产生最终的输出。神经网络中的神经元之间通过权重连接,权重决定了神经元之间的连接强度。
  • 神经网络的学习过程是通过调整权重来实现的。在训练过程中,神经网络会根据输入数据和期望输出,计算误差,并使用梯度下降等优化算法来调整权重,以减少误差。经过多次迭代,学习到输入数据和输出数据之间的关系,从而实现分类、回归等任务

激活函数:引入了非线性的学习和处理的能力

在这里插入图片描述

swish:

  • 在x为负值时,Swish函数输出的负值小于x本身,但不为0,这使得神经元保持一定的激活程度

  • 在零点附近平滑过渡,没有明确的分界点,这有助于梯度的稳定传播
    *

监督学习(有标注样本):

  • 标准的神经网络(Neural Networt):预测房屋价格;是否点击广告
  • 卷积神经网络(Convolutional NN):图像识别;
  • 循环神经网络(Recurrent NN,序列时间线的数据):音频识别;语言翻译
  • 混合神经网络:雷达;无人驾驶

无监督学习:

  • 给予机器没有标注的信息,希望通过算法进行一定的分析,得到一些结论
  • 常见任务:聚类、降维、找特征值

分布外数据(Out - of - Distribution,OOD):
原因:

  • 数据收集偏差:如果在数据收集过程中只关注了特定类型的数据,那么其他类型的数据就会成为 OOD 数据。例如,在收集图像数据时,如果只收集了室内场景的图片,那么室外场景的图片对于这个模型来说就是 OOD 数据。
  • 数据生成过程变化:当数据的生成机制发生变化时,也会产生 OOD 数据。例如,在时间序列数据中,经济环境的变化可能导致数据生成过程与之前不同,新的数据就可能是 OOD 数据

解决:

  • OOD 检测(Out - of - Distribution Detection):开发专门的方法来检测数据是否属于 OOD。例如,使用基于
    密度估计(概率分布)、距离度量(K-means)或分类器的方法来判断数据是否超出了训练数据的分布范围。

  • 模型适应(Model Adaptation):当发现 OOD 数据时,尝试对模型进行调整或重新训练,使其能够适应新的数据分布。例如,采用迁移学习或增量学习的方法,将已有模型的知识迁移到新的数据分布上,或者在新数据上逐步更新模型

前向和反向传播
通过前向传播,模型可以根据输入数据生成预测结果(forward),获取损失函数;
通过反向传播,可以计算模型的梯度信息(loss),从而进行参数优化。

  • 沿着正向传播的路线反向走!反向传播过程中利用下一层存储的值以及梯度的分向量来更新上一层的w和b,极大的提高了梯度计算速度,从而更加有利于利用梯度进行随机梯度下降更新神经网络参数完成机器学习训练任务
  • 先随机权重,计算loss,然后反向传播更新权重(通过就偏导知道该w对loss的影响,得出增大or缩小改w)

计算梯度的方法:

  • 随机梯度下降:代表随机抽样部分数据代替整体(随机一个批次),减少计算量,通过不断沿着反梯度方向(向量拆分)更新参数求解。学习率代表下降的步子,批量随机梯度下降是默认求解方法.
    • 缺点:收敛局部最小值;参数调整比较缓慢
  • 牛顿法:(求导求极值,求出所有找最优,计算量大)优化下降路径
  • 冲(动)量法:通过历史数据来修正每一次的梯度分量(有惯性),越远的影响越小,加权,减少震荡
  • AdaGrad:学习率自适应改动,历史数据的学习率加权,速度比不过冲量法
  • Adam:AdaGrad+动量法!

过拟合:
对于测试集的效果差,泛化能力差;可能训练数据带有噪音,或者参数过多导致模型复杂度高
解决办法:减少特征,清洗数据,更多训练样本,dropout,正则化

训练过程:
先随机权重,计算loss,然后反向传播更新权重(通过求偏导知道该w对loss的影响,得出增大or缩小改w)

Keras:
Keras是由纯python编写的基于theano/tensorflow的深度学习框架。
Keras是一个高层神经网络API,支持
a)简易和快速的原型设计(keras具有高度模块化,极简,和可扩充特性)
b)支持CNN和RNN,或二者的结合
c)无缝CPU和GPU切换

张量:数据的载体,把标量视为零阶张量,矢量视为一阶张量,那么矩阵就是二阶张量。
pooling: max/avg 降维度!!!减少数据量

顶级深度学习框架四大阵营:

  1. TensorFlow,前端框架Keras,背后巨头Google;
  2. PyTorch,前端框架FastAI,背后巨头Facebook;
  3. MXNet,前端框架Gluon,背后巨头Amazon;
  4. Cognitive Toolkit (CNTK),前端框架Keras或Gluon,背后巨头Microsoft。

深度学习框架的标准化–ONNX
开放神经网络交换(ONNX,“Open Neural Network Exchange)
ONNX是一个表示深度学习模型的开放格式。它使用户可以更轻松地在不同框架之间转移模型。
例如,它允许用户构建一个PyTorch模型,然后使用MXNet运行该模型来进行推理。

Tensorflow基本流程

  1. 使用图 (graph) 来表示计算任务.
  2. 在被称之为 会话 (Session) 的上下文 (context) 中执行图.
  3. 使用 tensor 表示数据.
  4. 通过 变量 (Variable) 维护状态.
  5. 使用 feed 和 fetch 可以为任意的操作(arbitrary operation)赋值或者从其中获取数据

相比下来pytorch好用很多哎。

手动实现一个神经网络

"""
work-从零训练一个简单的 识别图片数字的模型
"""
import numpy

# 加载数据 返回图片数组和对应label数组
def load_data_set(file_name):
    label = []
    img_data = []
    # 加载图片csv
    data_file = open(file_name)
    data_list = data_file.readlines()
    data_file.close()
    # data_list[0]是第一张图片,data_list[0].split(',')是按照','分割的字符串
    for data in data_list:
        # 第一个值对应的是图片的表示的数字,所以我们读取图片数据时要去掉第一个数值
        all_values = data.split(',')
        image_array = numpy.asfarray(all_values[1:]).reshape((28, 28))
        img_data.append(image_array)

        label.append(all_values[0])
    return img_data, label

# 建立模型结构
class NeuralNetWork:
    def __init__(self,input_nodes, hidden_nodes, output_nodes,lr):
        self.input_nodes = input_nodes
        self.hidden_nodes = hidden_nodes
        self.output_nodes = output_nodes
        self.lr = lr
        # 初始化权重
        self.wih = numpy.random.normal(0.0, pow(self.hidden_nodes, -0.5), (self.hidden_nodes, self.input_nodes))
        self.who = numpy.random.normal(0.0, pow(self.output_nodes, -0.5), (self.output_nodes, self.hidden_nodes))
        # 定义sigmoid 激活函数
        self.activation_function = lambda x: 1 / (1 + numpy.exp(-x))

    def train(self, inputs_list, targets_list):
        # 数据需要转换为 二维数组
        inputs = numpy.array(inputs_list, ndmin=2).T
        targets = numpy.array(targets_list, ndmin=2).T
        # 前向传播
        hidden_inputs = numpy.dot(self.wih, inputs)
        hidden_outputs = self.activation_function(hidden_inputs)
        final_inputs = numpy.dot(self.who, hidden_outputs)
        final_outputs = self.activation_function(final_inputs)
        # 反向传播
        # 计算loss
        output_loss = targets - final_outputs
        hidden_errors = numpy.dot(self.who.T, output_loss * final_outputs * (1 - final_outputs))
        self.who += self.lr * numpy.dot((output_loss * final_outputs * (1.0 - final_outputs)), numpy.transpose(hidden_outputs))
        self.wih += self.lr * numpy.dot((hidden_errors * hidden_outputs * (1.0 - hidden_outputs)), numpy.transpose(inputs))
    # 预测
    def query(self, inputs_list):
        inputs = numpy.array(inputs_list, ndmin=2).T
        hidden_inputs = numpy.dot(self.wih, inputs)
        hidden_outputs = self.activation_function(hidden_inputs)
        final_inputs = numpy.dot(self.who, hidden_outputs)
        final_outputs = self.activation_function(final_inputs)
        return final_outputs

# 测试模型效果
def predict(network):
    print("开始预测")
    img_data, true_label = load_data_set("dataset/mnist_test.csv")
    scores = []
    for i in range(len(img_data)):
        inputs = img_data[i]
        # 将图像数据从0-255的整数范围归一化到0.02-1.00的浮点数范围,以便更好地用于机器学习模型的训练和预测。、
        # 归一化处理可以加快模型的收敛速度,提高模型的性能
        inputs = (numpy.asfarray(inputs.reshape(-1))) / 255.0 * 0.99 + 0.01
        # 初始化one-hot
        targets = [0.01] * 10
        targets[int(true_label[i])] = 0.99
        outputs = network.query(inputs)
        # 找到数值最大的神经元对应的 编号
        label = numpy.argmax(outputs)
        print("predict  is : ", label)
        print("true  is : ", true_label[i])
        # print("网络认为图片的数字是:", label)
        if label == int(true_label[i]):
            scores.append(1)
        else:
            scores.append(0)
    # 计算图片判断的成功率
    scores_array = numpy.asarray(scores)
    print("perfermance = ", scores_array.sum() / scores_array.size)



def main():
    img_data, label = load_data_set("dataset/mnist_train.csv")
    # 定义超参数
    input_nodes = 784
    hidden_nodes = 200
    output_nodes = 10
    learning_rate = 0.01
    epochs = 5
    # 建立模型
    network = NeuralNetWork(input_nodes, hidden_nodes, output_nodes, learning_rate)
    for epoch in range(epochs):
        for i in range(len(img_data)):
            inputs = img_data[i]
            # 将图像数据从0-255的整数范围归一化到0.02-1.00的浮点数范围,以便更好地用于机器学习模型的训练和预测。、
            # 归一化处理可以加快模型的收敛速度,提高模型的性能
            inputs = (numpy.asfarray(inputs.reshape(-1))) / 255.0 * 0.99 + 0.01
            # 初始化one-hot
            targets = [0.01] * 10
            targets[int(label[i])] = 0.99
            network.train(inputs, targets)

    print("训练完成")
    predict(network)







if __name__ == '__main__':
    main()





补充一个tf和pytorch训练的demo

"""
week10-使用tf和pytorch



"""
import numpy
import numpy as np
import tensorflow as tf
from matplotlib import pyplot as plt

import torch
import torch.nn as nn
import torch.nn.functional as F
import torchvision
import torchvision.transforms as transforms


def tfDemo():
    # 使用numpy生成200个随机点
    x_data = np.linspace(-0.5, 0.5, 200)[:, np.newaxis]
    noise = np.random.normal(0, 0.02, x_data.shape)
    y_data = np.square(x_data) + noise
    # 定义两个placeholder存放输入数据
    x = tf.placeholder(tf.float32, [None, 1])
    y = tf.placeholder(tf.float32, [None, 1])
    # 定义神经网络中间层
    Weights_L1 = tf.Variable(tf.random_normal([1, 10]))
    biases_L1 = tf.Variable(tf.zeros([1, 10]))  # 加入偏置项
    Wx_plus_b_L1 = tf.matmul(x, Weights_L1) + biases_L1
    L1 = tf.nn.tanh(Wx_plus_b_L1)  # 加入激活函数
    # 定义神经网络输出层
    Weights_L2 = tf.Variable(tf.random_normal([10, 1]))
    biases_L2 = tf.Variable(tf.zeros([1, 1]))  # 加入偏置项
    Wx_plus_b_L2 = tf.matmul(L1, Weights_L2) + biases_L2
    prediction = tf.nn.tanh(Wx_plus_b_L2)  # 加入激活函数
    # 定义损失函数(均方差函数)
    loss = tf.reduce_mean(tf.square(y - prediction))
    # 定义反向传播算法(使用梯度下降算法训练)
    train_step = tf.train.GradientDescentOptimizer(0.1).minimize(loss)
    with tf.Session() as sess:
        sess.run(tf.global_variables_initializer())
        for i in range(2000):
            sess.run(train_step, feed_dict={x: x_data, y: y_data})

        # 用训练好的模型进行预测
        prediction_value = sess.run(prediction, feed_dict={x: x_data})
        # 可视化
        plt.figure()
        plt.scatter(x_data, y_data)
        plt.plot(x_data, prediction_value, 'r-', lw=5)
        plt.show()


# 使用pytorch实现数字图片识别
class torchDemo(torch.nn.Module):
    def __init__(self, input_dim, hidden_size, output_dim):
        super(torchDemo, self).__init__()
        self.input_dim = input_dim
        self.hidden_size = hidden_size
        self.output_dim = output_dim
        self.linear1 = nn.Linear(input_dim, hidden_size)
        self.linear2 = nn.Linear(hidden_size, hidden_size)
        self.output_liner = nn.Linear(hidden_size, output_dim)
        self.sigmoid = nn.Sigmoid()
        self.relu = nn.ReLU()
        self.loss = nn.CrossEntropyLoss()

    def forward(self, x):
        x = x.view(-1, 28 * 28)
        x = self.relu(self.linear1(x))
        x = self.relu(self.linear2(x))
        # 输出为10
        x = nn.functional.softmax(self.output_liner(x), dim=1)
        return x


def train(model, train_loader, num_epochs=3):
    optim = torch.optim.Adam(model.parameters(), lr=1e-5)  # 建立优化器
    for epoch in range(num_epochs):
        running_loss = 0.0
        for i, data in enumerate(train_loader, 0):
            inputs, labels = data
            optim.zero_grad()
            # forward + backward + optimize
            outputs = model(inputs)
            loss = model.loss(outputs, labels)
            loss.backward()
            optim.step()

            running_loss += loss.item()
            if i % 100 == 0:
                print('[epoch %d, %.2f%%] loss: %.3f' %
                      (epoch + 1, (i + 1) * 1. / len(train_loader), running_loss / 100))
                running_loss = 0.0

    print('Finished Training')


def evaluate(model, test_loader):
    correct = 0
    total = 0
    with torch.no_grad():  # no grad when test and predict
        for data in test_loader:
            images, labels = data

            outputs = model(images)
            predicted = torch.argmax(outputs, 1)
            total += labels.size(0)
            correct += (predicted == labels).sum().item()

    print('准确率为: %d %%' % (100 * correct / total))


# 加载数据 返回图片数组和对应label数组
def load_data_set():
    transform = transforms.Compose(
        [transforms.ToTensor(),
         transforms.Normalize([0, ], [1, ])])

    train_set = torchvision.datasets.MNIST(root='./data', train=True,
                                           download=True, transform=transform)
    train_loader = torch.utils.data.DataLoader(train_set, batch_size=32,
                                               shuffle=True, num_workers=2)

    test_set = torchvision.datasets.MNIST(root='./data', train=False,
                                          download=True, transform=transform)
    test_loader = torch.utils.data.DataLoader(test_set, batch_size=32, shuffle=True, num_workers=2)
    return train_loader, test_loader


if __name__ == '__main__':
    # tfDemo()
    train_loader, test_loader = load_data_set()
    model = torchDemo(28 * 28, 512, 10)
    train(model, train_loader, 3)
    evaluate(model, test_loader)


网站公告

今日签到

点亮在社区的每一天
去签到