二、机器学习基本原理

68 阅读5分钟

1、基本数学知识

标量:标量也就是一个单独的数 向量:类似[1,2,3,4]被称之为向量,是一列数;其中可以进行的运算有加法运算以及向量之间做内积 向量加法:i.e. [a1,a2,a3]+[b1,b2,b3]=[a1+b1,a2+b2,a3+b3] 向量内积:i.e. [a1,a2,a3]*[b1,b2,b3]= a1*b1+a2*b2+a3*b3 张量:张量是Pytoch框架中通用的数据类型,类似矩阵之类的数据,都必须转换为张量才能输入Pytorch框架中以供模型进行训练 矩阵:矩阵是一组具有行列的数列,其中最重要的运算法则是矩阵乘法满足结合律以及分配律 矩阵乘法: a=N*M, b=M*C 则 a*b=N*C 矩阵点乘:对位相乘,前提条件是两个矩阵的形状必须一致 导数:通俗的理解是导数是对应函数在某一点上的变化趋势, 在这里插入图片描述

2、纯Python代码模拟机器学习

import math
import sys
import matplotlib.pyplot as plt


# 定义模型
def fun(x, w):
    return w[0]*x**2+w[1]*x+w[2]


# 定义损失函数:使用均方差
def loss(pre_data, true_date):
    return (pre_data-true_date)**2


# 模拟训练过程
def train(train_date, standard_output, w, lr):
    for epoch in range(1000):
        loss_value = 0
        count = 0
        batch_size = 20
        grad1, grad2, grad3 = 0, 0, 0
        for x, y in zip(train_date, standard_output):
            y_pred = fun(x, w)
            loss_value += loss(y_pred, y)
            count += 1
            # 计算梯度
            grad1 += 2*(y_pred-y)*x**2
            grad2 += 2*(y_pred-y)*x
            grad3 += 2*(y_pred-y)
            #更新权重
            if count == batch_size:
                w[0] = w[0] - lr*grad1/batch_size
                w[1] = w[1] - lr*grad2/batch_size
                w[2] = w[2] - lr*grad3/batch_size
                count = 0
                grad1, grad2, grad3 = 0, 0, 0
        loss_value = loss_value/len(train_date)
        if loss_value <= 0.00001:
            break


if __name__ == "__main__":
    X = [i*0.01 for i in range(1, 101)]
    Y = [3*x**2+4*x+7 for x in X]
    w = [1, 0, -1]
    lr = 0.1
    train(X, Y, w, lr)
    print(f"权重:w1={w[0]},w1={w[1]},w2={w[2]}")
    Y1 = [w[0]*x**2+w[1]*x+w[2] for x in X]
    plt.plot(X, Y, label='y=3x^2+4x+7', color='blue', marker='o')
    plt.plot(X, Y1, label='y=w[0]x^2+w[1]x+w[2]', color='red', marker='x')

    plt.xlabel("x Axis")
    plt.ylabel("y Axis")
    plt.legend()
    plt.show()

最终效果: 在这里插入图片描述 在这里插入图片描述

3、Pytorch框架基本组件

3.1 线性层

概述:线性层是其网络结构中最基本的一层,能够获取到训练数据的数据特征 基本形式: y=w*x+b,其中w,b为训练参数。 在这里插入图片描述

3.2 激活函数

概述:该函数的作用使的函数具有非线性的作用,例如一个分类任务中你无法通过一条直线将散乱的数据分为两类而必须通过一条曲 线来进行数据的分类。 常用的激活函数:

  • ReLU:
    在这里插入图片描述在这里插入图片描述
  • sigmoid:
    在这里插入图片描述
    在这里插入图片描述
  • tanh:
    在这里插入图片描述
    在这里插入图片描述
  • softmax:该激活函数主要作用于分类任务,该函数映射之后的同一维度的元素之和为1,
    在这里插入图片描述
  • GELU:是目前比较先进的激活函数,具有传统生物神经元的软门控特性
    在这里插入图片描述

3.3 损失函数

概述:该函数主要的作用主要是用于计算预测值与真实值之间的差值,也就是模型的拟合效果;进而通过该函数计算梯度并更新权 重,损失函数主要分为均方差损失函数以及交叉熵损失函数。

  • 均方差损失函数:主要用于求值类任务
    在这里插入图片描述
  • 交叉熵损失函数:该函数主要用于分类任务的计算,在 Pytorch框架中使用交叉熵损失函数CrossEntropyLoss其内部操作相当于使用了 LogSoftmax+NLLLoss进行,下面展示交叉熵的计算逻辑
    在这里插入图片描述

4、实现从随机五个数中分析出正样本以及负样本model训练

任务描述:完成任务目标比较一个五维向量第一个数比第二个数大,是为正样本,否为负样本

import torch
import torch.nn as nn
import matplotlib.pyplot as plt
import numpy as np

# 完成任务目标比较一个五维向量第一个数比第二个数大,是为正样本,否为负样本


# 构建标准训练数据
def build_data(number):
    train_y = []
    train_x = []
    for i in range(number):
        x = np.random.rand(5)
        if x[0] >= x[4]:
            train_y.append([1])
        else:
            train_y.append([0])
        train_x.append(x)
    return torch.FloatTensor(train_x), torch.FloatTensor(train_y)


# 搭建训练模型
class max_model(nn.Module):
    def __init__(self):
        super(max_model, self).__init__()
        self.linear1 = nn.Linear(5, 1)
        self.sigmoid = torch.sigmoid
        self.loss = nn.functional.mse_loss

    def forward(self, x, y_true=None):
        x = self.linear1(x)
        y_pred = self.sigmoid(x)
        if y_true is not None:
            loss = self.loss(y_pred, y_true)
            return loss
        else:
            return y_pred


# 训练模型
def train(model):
    round_number = 100         # 训练轮数
    batch_size = 100            # 批次大小
    lr = 0.001                   # 学习率

    # 优化器
    optimizer = torch.optim.Adam(model.parameters(), lr)

    # 构建训练数据
    train_x, train_y = build_data(3000)
    log = []

    # 训练
    for num_epoch in range(round_number):
        model.train()
        loss_value = []
        for index in range(3000//batch_size):
            x = train_x[index*batch_size:(index*batch_size+batch_size)]
            y = train_y[index*batch_size:(index*batch_size+batch_size)]
            loss = model(x, y)      # 计算损失
            loss.backward()         # 计算梯度
            optimizer.step()        # 梯度更新
            optimizer.zero_grad()   # 梯度归零
            loss_value.append(loss.item())
        loss_avg = np.mean(loss_value)
        rate = test(model)
        print(rate)
        log.append([loss_avg, rate])
        if loss_avg < 1e-3:
            break
    # 保存模型
    torch.save(model.state_dict(), 'model/model.bin')
    # 可视化损失值的变化趋势
    plt.plot(list(range(len(log))), [loss[0] for loss in log], color='red', label='loss')
    plt.plot(list(range(len(log))), [rate[1] for rate in log], color='blue', label='rate')
    plt.title('Accuracy rate')     # 标题
    plt.legend()
    plt.xlabel('index')         # x轴标签
    plt.ylabel('value')         # y轴标签
    plt.show()


# 测试模型效果
def test(model):
    # 构建测试数据
    test_x, test_y = build_data(100)
    correct = 0
    worry = 0
    model.eval()
    with torch.no_grad():
        for i in range(len(test_x)):
            y_pred = model(test_x[i])
            if y_pred >= 0.5 and test_y[i] == 1:
                correct += 1
            elif y_pred < 0.5 and test_y[i] == 0:
                correct += 1
            else:
                worry += 1
    return correct/len(test_x)


# 获取模型进行预测
def prediction(data):
    model = max_model()
    # 加载模型
    model.load_state_dict(torch.load('model/model.bin', weights_only= True))
    model.eval()
    with torch.no_grad():
        for x in data:
            y_pred = model(x)
            if round(y_pred.item()) == 1:
                print(f"{x},预测值{y_pred},为正样本")
            elif round(y_pred.item()) == 0:
                print(f"{x},预测值{y_pred},为负样本")


if __name__ == "__main__":
	# 训练模型步骤
    # model = max_model()
    # train(model)

	#测试模型训练效果
    x, y = build_data(5)
    prediction(x)

最终训练效果:
在这里插入图片描述
最终模型测试效果:
在这里插入图片描述