人工智能 | 用Kimi写一个BP神经网络

上一节楼主介绍了BP神经网络的基础,列出了一大堆公式,初学者肯定觉得很疑惑,这些公式有什么用处,一个BP神经网络又能用来干什么呢?本章是个简单的用BP神经网络实现分类的例子,楼主让人工智能Kimi写了一个BP神经网络的matlab的代码,实现了任意输入一个坐标(x,y),输出其坐标象限的功能。

一、任务说明

对于一个直角坐标系,其输入为(x,y),用BP神经网络指出当前坐标所在的象限,用一个向量来表示象限,其图示如下:

图5 输入坐标及输出表示

                    

这个任务很简单,根据输入(x,y)的符号判断一下就行,如果写代码,用if.....else....就可以快速实现,似乎用不着神经网络这么高大上的东西?其实不是的,举这个例子是为了理解BP神经网络的学习过程,先从一个简单直观的例子切入,掌握之后再逐渐解决更复杂更高级的问题,这是一个循序渐进的过程。

把分类问题抽象出来之后,很多人还是下不了手,似乎理论到实践还有一条鸿沟,毕竟coding是个拦路虎,但是现在不一样了,我们有了人工智能这个工具,接下来,让Kimi帮我们开个头。

二、Kimi首秀

打开Kimi,直接输入自己的需求,Kimi确实给出了一段代码,它选择的是最简单的二分类问题,写的还算有模有样,也谦虚的表明“这只是一个基础的示例,实际应用中可能需要根据问题进行调整”。

图6 Kimi的BP神经网络

可能有人会疑惑,楼主干嘛不让它直接写个坐标四分类的代码呢?楼主其实试过,和Kimi纠缠了半天,各种启发引导,它写的还不如一开始的二分类,楼主没耐心了,对于一个程序员来说,改一个代码比写一个代码更让人抓狂,二分类就二分类吧,改成四分类是分分钟的事情,楼主就用Kimi写的二分类改一个四分类出来,Kimi写的二分类是这样的:

% 随机生成一些数据用于训练和测试(假设为二分类问题)
data = rand(100, 2); % 100个样本,每个样本2个特征
labels = randi([0, 1], 100, 1); % 100个标签,0或1

% 定义网络参数
inputSize = 2; % 输入层神经元数量
hiddenSize = 5; % 隐藏层神经元数量
outputSize = 1; % 输出层神经元数量(二分类问题)

% 初始化权重和偏置
inputToHiddenWeights = rand(inputSize, hiddenSize) - 0.5;
inputToHiddenBias = zeros(1, hiddenSize);
hiddenToOutputWeights = rand(hiddenSize, outputSize) - 0.5;
hiddenToOutputBias = 0;

% 学习率
learningRate = 0.01;

% 前向传播和损失函数
for epoch = 1:1000
    for i = 1:size(data, 1)
        % 输入层到隐藏层
        input = data(i, :);
        hiddenInput = input * inputToHiddenWeights' + inputToHiddenBias;
        hiddenOutput = sigmoid(hiddenInput);
        
        % 隐藏层到输出层
        outputInput = hiddenOutput * hiddenToOutputWeights + hiddenToOutputBias;
        output = sigmoid(outputInput);
        
        % 计算损失
        loss = -labels(i) * log(output + 1e-8) - (1 - labels(i)) * log(1 - output + 1e-8);
        
        % 反向传播
        outputError = -(labels(i) - output) / (output * (1 - output));
        hiddenError = outputError * hiddenToOutputWeights' * (hiddenOutput * (1 - hiddenOutput));
        
        % 更新权重和偏置
        hiddenToOutputWeights = hiddenToOutputWeights + hiddenOutput' * outputError * learningRate;
        hiddenToOutputBias = hiddenToOutputBias + outputError * learningRate;
        inputToHiddenWeights = inputToHiddenWeights + input' * hiddenError * learningRate;
        inputToHiddenBias = inputToHiddenBias + hiddenError * learningRate;
    end
    
    % 每100个epoch打印一次损失
    if mod(epoch, 100) == 0
        disp(['Epoch ', num2str(epoch), ': loss = ', num2str(loss)]);
    end
end

% 测试网络
testData = rand(10, 2); % 随机生成10个测试样本
for i = 1:size(testData, 1)
    hiddenInput = testData(i, :) * inputToHiddenWeights' + inputToHiddenBias;
    hiddenOutput = sigmoid(hiddenInput);
    output = sigmoid(hiddenToOutputWeights * hiddenOutput + hiddenToOutputBias);
    
    % 打印预测结果
    fprintf('Output: %f, Class: %d\n', output, round(output));
end

% 辅助函数:Sigmoid激活函数
function g = sigmoid(z)
    g = 1 ./ (1 + exp(-z));
end

三、BP实现四分类

首先肯定Kimi的工作,它清楚的写出了“训练”和“测试”这两个步骤,训练时的两个for循环逻辑正确,隐藏层和输出层的计算公式也是对的,sigmoid及其求导也没问题,但是这个代码,它跑不起来。

楼主仔细看了一下,Kimi没有正确区分matlab中的“.*”和“*”,造成维度对应不上,楼主改了一遍,它跑起来了,Kimi还是值得表扬的。现在可以完成坐标四分类的任务了,楼主做了以下三个的修改:

  1. 重新定义了data,把它指定成[-1,1]内的随机数。
  2. 重新定义了labels,做了if.....else.....判断,获得图5所示的标准输出。
  3. outputSize改成4,输出格式改的更符合楼主的需求。

改好的代码如下:

close all;
clear all;
clc;

% 定义网络参数
inputSize = 2; % 输入层神经元数量
hiddenSize = 5; % 隐藏层神经元数量
outputSize = 4; % 输出层神经元数量(四分类问题)

% 随机生成一些数据用于训练和测试(假设为四分类问题)
inputNum = 100;
% data     = rand(inputNum, inputSize); % 100个样本,每个样本2个特征
data     = rand(inputNum, inputSize)*2-1;
labels   = zeros(inputNum,outputSize);
for i = 1 : inputNum
    if ((data(i,1)>0) && (data(i,2)>0))
        labels(i,:) = [1,0,0,0];
    elseif ((data(i,1)<0) && (data(i,2)>0))
        labels(i,:) = [0,1,0,0];
    elseif ((data(i,1)<0) && (data(i,2)<0))
        labels(i,:) = [0,0,1,0];
    else
        labels(i,:) = [0,0,0,1];
    end
end

% labels   = randi([0, 1], inputNum, outputSize); % 100个标签,0或1

% 初始化权重和偏置
inputToHiddenWeights = rand(inputSize, hiddenSize) - 0.5;
inputToHiddenBias = zeros(1, hiddenSize);
hiddenToOutputWeights = rand(hiddenSize, outputSize) - 0.5;
hiddenToOutputBias = 0;

% 学习率
learningRate = 0.01;

% 前向传播和损失函数
for epoch = 1:1000
    for i = 1:size(data, 1)
        % 输入层到隐藏层
        input = data(i,:);
        hiddenInput = input * inputToHiddenWeights + inputToHiddenBias;
        hiddenOutput = sigmoid(hiddenInput);
        
        % 隐藏层到输出层
        outputInput = hiddenOutput * hiddenToOutputWeights + hiddenToOutputBias;
        output = sigmoid(outputInput);
        
        % 计算损失
        loss = -labels(i) * log(output + 1e-8) - (1 - labels(i)) * log(1 - output + 1e-8);
        
        % 反向传播
        outputError = (labels(i,:) - output) .* (output .* (1 - output));
        hiddenError = (hiddenOutput .* (1 - hiddenOutput)) .* (hiddenToOutputWeights * outputError')';
        
        % 更新权重和偏置
        hiddenToOutputWeights = hiddenToOutputWeights + hiddenOutput' * outputError * learningRate;
        hiddenToOutputBias = hiddenToOutputBias + outputError * learningRate;
        inputToHiddenWeights = inputToHiddenWeights + input' * hiddenError * learningRate;
        inputToHiddenBias = inputToHiddenBias + hiddenError * learningRate;
    end
    
    % 每100个epoch打印一次损失
    if mod(epoch, 100) == 0
        disp(['Epoch ', num2str(epoch), ': loss = ', num2str(loss)]);
    end
end

% 测试网络
testData = rand(10, inputSize)*2-1; % 随机生成10个测试样本
testOut  = zeros(inputSize,outputSize);
for i = 1:size(testData, 1)
    hiddenInput  = testData(i,:) * inputToHiddenWeights + inputToHiddenBias;
    hiddenOutput = sigmoid(hiddenInput);
    output       = sigmoid(hiddenOutput * hiddenToOutputWeights + hiddenToOutputBias);
    testOut(i,:) = round(output);
    
    % 打印预测结果
    fprintf('index=%d, Input: [%f,%f], Class: [%d,%d,%d,%d]\n', i, testData(i,:), round(output));
end

楼主跑出的结果如下:

图7 四分类结果

四、总结

以这个代码作为基础版本,可以增加层数、增加节点数或者更换激活函数等,如果想要python的代码,也可以让Kimi写,可以说有了人工智能,基本上实现了代码自由。接下来楼主要慢慢尝试其他更复杂一些的神经网络,并逐渐与ISP的处理结合起来。

  • 11
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大凝的IC进阶之路

一起学习一起进步

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值