感知机和线性单元的C#版本

时间:2023-03-08 16:02:47

本文的原版Python代码参考了以下文章:

零基础入门深度学习(1) - 感知器

零基础入门深度学习(2) - 线性单元和梯度下降

在机器学习如火如荼的时代,Python大行其道,几乎所有的机器学习的程序都是Python写的。

.Net的机器学习库有,但是非常少,Tensorflow也暂时并不支持.Net.

写这篇文章的目的,也只是想尝试一下,通过将Python的源代码改写成Net来更加深入的理解感知机的原理。

毕竟在改写的时候,每一行代码都必须研究一下,很多知识是无法混过去的。

感知机和线性单元的C#版本

感知机的模型其实就这么简单,本文也不是深度学习的科普,所以具体不解释。

(题外话 .Net Core 暂时没有System.Math的支持,对于一些简单的机器学习,改写起来没有问题,但是稍微复杂一些就无能为力了。)

一个感知机的代码大概是这个样子的,这里矩阵的实现还是很原始的List<List>的方法不知道是否有其他写法。

代码的话,如果你看了上面的文章,就很容易理解了。

文章只有标题,因为我不知道我看到的是不是原文,所以请大家自行百度。

using System;
using System.Collections.Generic; public class Perceptron
{ private float bias = 0.0f; private List<float> weights = new List<float>(); private Func<float, float> activator; public Perceptron(int input_num, Func<float, float> Activator)
{
for (int i = 0; i < input_num; i++)
{
weights.Add(0.0f);
} activator = Activator; bias = 0.0f;
} public override string ToString()
{
var s = "weights:";
foreach (var weight in weights)
{
s += weight + System.Environment.NewLine;
}
s += "bias:" + this.bias;
return s;
} public float Predict(List<float> input_vec)
{
//这里规定向量长度和权重长度相等
float sum = 0.0f;
for (int i = 0; i < weights.Count; i++)
{
sum += input_vec[i] * weights[i];
}
//偏置项
sum += bias;
return activator(sum);
} public void train(List<List<float>> Input_vecs, List<float> labels, int interation, float rate)
{
for (int i = 0; i < interation; i++)
{
one_iteration(Input_vecs, labels, rate);
}
} private void one_iteration(List<List<float>> Input_vecs, List<float> labels, float rate)
{
for (int i = 0; i < labels.Count; i++)
{
var output = Predict(Input_vecs[i]);
update_weights(Input_vecs[i], output, labels[i], rate);
}
} private void update_weights(List<float> input_vec, float output, float label, float rate)
{
var delta = label - output;
for (int i = 0; i < weights.Count; i++)
{
weights[i] += rate * delta * input_vec[i];
}
//更新bias
bias += rate * delta;
} }

测试代码如下:

AndDemo是通过感知机模拟一个AND函数,LinearUnitDemo则是模拟一个线性单元函数。

using System;
using System.Collections.Generic; namespace CSharp
{
class Program
{
static void Main(string[] args)
{
AndDemo();
LinearUnitDemo();
} static void LinearUnitDemo()
{
Func<float, float> activator = (x) => { return x; };
Perceptron p = new Perceptron(1, activator);
List<List<float>> Input_vecs = new List<List<float>>();
Input_vecs.Add(new List<float>());
Input_vecs.Add(new List<float>());
Input_vecs.Add(new List<float>());
Input_vecs.Add(new List<float>());
Input_vecs.Add(new List<float>());
Input_vecs[0].Add(5);
Input_vecs[1].Add(3);
Input_vecs[2].Add(8);
Input_vecs[3].Add(1.4f);
Input_vecs[4].Add(10.1f); List<float> labels = new List<float>();
labels.Add(5500);
labels.Add(2300);
labels.Add(7600);
labels.Add(1800);
labels.Add(11400);
p.train(Input_vecs, labels, 50, 0.01f); System.Console.WriteLine(p.ToString()); System.Console.WriteLine(Input_vecs[0][0] + " years: " + p.Predict(Input_vecs[0]));
System.Console.WriteLine(Input_vecs[1][0] + " years: " + p.Predict(Input_vecs[1]));
System.Console.WriteLine(Input_vecs[2][0] + " years: " + p.Predict(Input_vecs[2]));
System.Console.WriteLine(Input_vecs[3][0] + " years: " + p.Predict(Input_vecs[3]));
System.Console.WriteLine(Input_vecs[4][0] + " years: " + p.Predict(Input_vecs[4]));
} static void AndDemo()
{ Func<float, float> activator = (x) => { return x > 0 ? 1.0f : 0.0f; };
Perceptron p = new Perceptron(2, activator);
List<List<float>> Input_vecs = new List<List<float>>();
Input_vecs.Add(new List<float>());
Input_vecs.Add(new List<float>());
Input_vecs.Add(new List<float>());
Input_vecs.Add(new List<float>());
Input_vecs[0].Add(1);
Input_vecs[0].Add(1);
Input_vecs[1].Add(0);
Input_vecs[1].Add(0); Input_vecs[2].Add(1);
Input_vecs[2].Add(0);
Input_vecs[3].Add(0);
Input_vecs[3].Add(1); List<float> labels = new List<float>();
labels.Add(1);
labels.Add(0);
labels.Add(0);
labels.Add(0);
p.train(Input_vecs, labels, 10, 0.1f); System.Console.WriteLine(p.ToString());
System.Console.WriteLine("1 and 1 =" + p.Predict(Input_vecs[0]));
System.Console.WriteLine("0 and 0 =" + p.Predict(Input_vecs[1]));
System.Console.WriteLine("1 and 0 =" + p.Predict(Input_vecs[2]));
System.Console.WriteLine("0 and 1 =" + p.Predict(Input_vecs[3])); }
}
}

对于机器学习感兴趣的同学可以关注一下微信号 "TensorFlow教室" 一起学习机器学习,深度学习,自然语言处理。