首页 > 编程语言 >用C#实现感知器算法——从零开始打造一个简单的机器学习模型!

用C#实现感知器算法——从零开始打造一个简单的机器学习模型!

时间:2024-12-20 21:19:59浏览次数:3  
标签:偏置 感知器 C# double sum int 从零开始 weights

感知器(Perceptron)是一个经典的机器学习算法,常用于二分类问题。它是神经网络的基础,最早由Frank Rosenblatt在1958年提出。今天,我们将用C#实现一个简单的感知器算法,让你理解感知器的工作原理,并能够亲自编码一个可用的模型。


一、感知器算法概述

感知器是一种线性分类器,其核心思想是通过调整权重(weights)和偏置(bias),使得模型能够根据输入数据进行分类。感知器通过迭代优化这些参数,最终得到一个超平面来分割不同类别的数据。

1. 感知器模型的工作原理

感知器的基本结构如下:

  1. 输入层:接收输入数据。

  2. 加权求和:每个输入与对应的权重相乘,并加上偏置项。

  3. 激活函数:将加权和通过一个阈值(通常为零)转换为输出。

感知器的输出 ( y ) 可以通过以下公式表示: [ y = \text{sign}(w_1x_1 + w_2x_2 + ... + w_nx_n + b) ]

  • ( w ):权重向量

  • ( x ):输入向量

  • ( b ):偏置

  • (\text{sign}) 是符号函数,输出1或-1

感知器的目标是找到最优的权重和偏置,使得分类误差最小。

2. 感知器的训练过程

感知器的训练过程就是不断调整权重和偏置,以最小化预测值和真实标签之间的差异。更新规则如下:

  • 如果预测正确,权重保持不变。

  • 如果预测错误,则更新权重和偏置: [ w = w + \eta \cdot (y{\text{true}} - y{\text{pred}}) \cdot x ] [ b = b + \eta \cdot (y{\text{true}} - y{\text{pred}}) ] 其中,(\eta) 是学习率,( y{\text{true}} ) 和 ( y{\text{pred}} ) 分别是实际标签和预测标签。


二、用C#实现感知器

现在,让我们用C#来实现一个简单的感知器算法,应用于经典的“与(AND)”或“或(OR)”二分类问题。

1. 感知器类的实现

我们首先定义一个感知器类,包含初始化权重、训练模型和预测函数。

using System;

public class Perceptron
{
   private double[] weights;
   private double bias;
   private double learningRate;

   public Perceptron(int inputSize, double learningRate = 0.1)
  {
       weights = new double[inputSize];
       bias = 0;
       this.learningRate = learningRate;
  }

   // 激活函数
   private int Activate(double sum)
  {
       return sum >= 0 ? 1 : -1;  // 阈值函数
  }

   // 训练感知器
   public void Train(double[][] inputs, int[] labels, int epochs)
  {
       for (int epoch = 0; epoch < epochs; epoch++)
      {
           for (int i = 0; i < inputs.Length; i++)
          {
               // 计算加权和
               double sum = 0;
               for (int j = 0; j < weights.Length; j++)
              {
                   sum += inputs[i][j] * weights[j];
              }
               sum += bias;

               // 获取预测结果
               int prediction = Activate(sum);

               // 更新权重和偏置
               if (prediction != labels[i])
              {
                   for (int j = 0; j < weights.Length; j++)
                  {
                       weights[j] += learningRate * (labels[i] - prediction) * inputs[i][j];
                  }
                   bias += learningRate * (labels[i] - prediction);
              }
          }
      }
  }

   // 预测
   public int Predict(double[] input)
  {
       double sum = 0;
       for (int i = 0; i < weights.Length; i++)
      {
           sum += input[i] * weights[i];
      }
       sum += bias;
       return Activate(sum);
  }

   // 输出当前权重和偏置
   public void PrintWeights()
  {
       Console.WriteLine("Weights: " + string.Join(", ", weights));
       Console.WriteLine("Bias: " + bias);
  }
}

2. 训练和测试感知器

接下来,我们来创建一个简单的训练集,应用感知器训练和预测。

class Program
{
   static void Main(string[] args)
  {
       // 定义“与(AND)”问题的输入和输出
       double[][] inputs = {
           new double[] {0, 0},
           new double[] {0, 1},
           new double[] {1, 0},
           new double[] {1, 1}
      };

       // 输出:与(AND)问题的期望结果
       int[] labels = { -1, -1, -1, 1 };  // 0 AND 0 = 0, 0 AND 1 = 0, 1 AND 0 = 0, 1 AND 1 = 1

       // 创建感知器实例
       Perceptron perceptron = new Perceptron(inputSize: 2);

       // 训练感知器
       perceptron.Train(inputs, labels, epochs: 10);

       // 输出训练结果
       perceptron.PrintWeights();

       // 测试预测
       Console.WriteLine("Prediction for [1, 1]: " + perceptron.Predict(new double[] { 1, 1 }));
       Console.WriteLine("Prediction for [0, 0]: " + perceptron.Predict(new double[] { 0, 0 }));
  }
}

三、代码分析

  1. 感知器初始化:我们为每个输入分配了一个初始权重,并设置了一个学习率。初始化时,偏置设为0,权重随机设置。

  2. 训练过程:每一轮训练(epochs)都会遍历整个训练集,计算加权和,并更新权重。如果预测错误,权重和偏置会根据公式进行调整。

  3. 预测:对于新的输入,感知器会计算加权和,并通过激活函数得到最终的预测值。


四、如何使用感知器?

感知器适用于线性可分的二分类问题,例如:

  • “与(AND)”问题

  • “或(OR)”问题

  • 基于特征的分类问题,如文本分类等。

然而,感知器存在局限性:它无法解决线性不可分的问题(如异或问题),但它为后续神经网络的发展提供了基础。


五、总结

通过本篇文章,你已经学会了如何用C#实现一个简单的感知器模型,并且了解了感知器的工作原理和训练过程。虽然感知器在某些问题上具有局限性,但它依然是机器学习的入门模型,非常适合帮助你理解深度学习中的基本概念。

如果你想深入学习机器学习的其他算法,或者对神经网络有兴趣,可以从感知器开始,逐步扩展到更复杂的模型。

 

标签:偏置,感知器,C#,double,sum,int,从零开始,weights
From: https://www.cnblogs.com/forges/p/18619991

相关文章

  • C++面向对象
    目录C++核心类和对象对象特性友元运算符重载继承多态文件读写C++核心类和对象类和对象类和对象是C++面向对象的基础,在C++中万事万物都是对象,C++利用类来实例化对象,下面是创建一个Circle类并实例化的语法://创建类classCircle{public:intm_r;voidgetM_......
  • 对 Windows 备份 应用以及 WebExperienceHost 应用的删除和封装。具体来说,您提到删除
    对Windows备份应用以及WebExperienceHost应用的删除和封装。具体来说,您提到删除AppxManifest.xml文件中的WebExperienceHost应用和WindowsBackupClient.exe,这些操作通常用于定制和优化Windows系统,尤其是进行封装、去除不必要的系统应用或服务。以下是详细步骤及说明,......
  • C++STL与泛型编程
    目录C++提高编程模版STL初识StringVectorDequeStackQueueListSetPairMap其它函数对象谓词STL常见算法遍历算法查找算法排序算法拷贝和替换算法算术生成算法常见集合算法C++提高编程本阶段主要针对C++泛型编程和STL技术做详细讲解模版C++另一种编程思想称为泛型编程,主要利用......
  • Get-WmiObject -Class Win32_SystemEnclosure -Namespace "root\CIMV2" | Select-Obj
    Get-WmiObject-ClassWin32_SystemEnclosure-Namespace"root\CIMV2"|Select-ObjectChassisTypes这条PowerShell命令用于查询计算机的硬件外壳(Chassis)信息,特别是返回系统机箱类型(ChassisTypes)。解释命令的组成部分:Get-WmiObject:这是一个用于查询WindowsManagement......
  • 题解:CF917A The Monster
    思路分别枚举连续子序列所有起点的可能。用变量来记录左括号和右括号的数量,左括号\(+1\),右括号\(-1\)。对于问号,则通过当前左括号和右括号的数量来判断应该变为右括号还是变为左括号。当右括号数量大于左括号数量时,就可以停止枚举以当前起点为起点的连续子序列了,因为无论怎......
  • 题解:CF603A Alternative Thinking
    思路你猜这个题为什么是A题?很思维的解法。只允许翻转一次,所以最多只会在原答案上加\(2\)。所以我们来讨论仅有的三种可能:加\(2\),要有两段连续的\(0\)或\(1\)。加\(1\),要有一段连续的\(0\)或\(1\)。不加,没有连续的\(0\)或\(1\)。我们的代码模拟上面的三种......
  • 题解:CF626B Cards
    思路枚举三种能够得到该颜色的方法。全是该颜色的卡牌。另外两种卡牌的数量都大于等于一张。另外的两种卡牌,一种大于等于两张,一种为零张,该颜色的卡牌大于等于一张。我们用三个变量来记录每种卡牌出现的次数,然后按照以上的三种方法模拟即可。AC代码#include<bits/stdc++.......
  • 题解:CF1540A Great Graphs
    思路CF思维题。因为我们要让边权值最小,所以可以利用贪心思想先将数组\(d\)进行升序排序。然后再预处理出每一条边的权重。其次我们来想一下如何处理答案,因为这道题说图中不能出现负环和重边,所以我们可以通过加反方向负边的方法来解决这道题。因为对于一条边,这条边之后的所......
  • NV12数据转OpenCV的Mat
    //将NV12转换为BGRvoidnv12ToBgr(constunsignedchar*yuvData,intwidth,intheight,Mat&bgrImage){//计算每个平面的大小intySize=width*height;intuvSize=(width/2)*(height/2);//创建一个包含NV12数据的Mat对象Ma......
  • 数据结构漫游记:静态链表的实现(CPP)
    嘿,各位技术潮人!好久不见甚是想念。生活就像一场奇妙冒险,而编程就是那把超酷的万能钥匙。此刻,阳光洒在键盘上,灵感在指尖跳跃,让我们抛开一切束缚,给平淡日子加点料,注入满满的passion。准备好和我一起冲进代码的奇幻宇宙了吗?Let'sgo!我的博客:yuanManGan我的专栏:C++入门小馆 C......