百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 热门文章 > 正文

Go语言初学者入门指南:从零开始,构建简单的神经网络

bigegpt 2024-08-12 14:21 2 浏览


介绍

在本教程中,我们将在Golang中从头开始构建一个简单的神经网络(单层感知器)。我们还将根据样本数据对其进行培训并进行预测。从头开始创建自己的神经网络将帮助您更好地了解神经网络内部发生的事情以及学习算法的工作。

什么是感知器?

感知器——由Frank Rosenblatt于1958年发明,是最简单的神经网络,由n个输入、1个神经元和1个输出组成,其中n是我们数据集的特征数。

因此,我们的单层感知器由以下组件组成:

  • 输入层(x)
  • 输出层(?)
  • 这两层之间的一组权重(w)和一个偏差(b)
  • 输出层的激活函数(σ)。在本教程中,我们将使用sigmoid激活函数。

我们的神经网络被称为单层感知器(SLP),因为神经网络只有一层神经元。具有一层以上神经元的神经网络称为多层感知器(MLP)。

(注:epoch是指整个训练数据集的一个周期)

type Perceptron struct {
	input        [][]float64
	actualOutput []float64
	weights      []float64
	bias         float64
	epochs       int
}

开始之前

我们将为以下数学运算构建自己的函数-向量加法、向量点积和标量矩阵乘法。

func dotProduct(v1, v2 []float64) float64 { //Dot Product of Two Vectors of same size
	dot := 0.0
	for i := 0; i < len(v1); i++ {
		dot += v1[i] * v2[i]
	}
	return dot
}

func vecAdd(v1, v2 []float64) []float64 { //Addition of Two Vectors of same size
	add := make([]float64, len(v1))
	for i := 0; i < len(v1); i++ {
		add[i] = v1[i] + v2[i]
	}
	return add
}

func scalarMatMul(s float64, mat []float64) []float64 { //Multiplication of a Vector & Matrix
	result := make([]float64, len(mat))
	for i := 0; i < len(mat); i++ {
		result[i] += s * mat[i]
	}
	return result
}

最初,神经网络的权值设置为0到1之间的随机浮点数,而偏差设置为0。

func (a *Perceptron) initialize() { //Random Initialization
	rand.Seed(time.Now().UnixNano())
	a.bias = 0.0
	a.weights = make([]float64, len(a.input[0]))
	for i := 0; i < len(a.input[0]); i++ {
		a.weights[i] = rand.Float64()
	}
}

正向传播

通过神经网络传递数据的过程称为前向传播或前向传递。感知器的输出是:

简而言之,权向量(w)和输入向量(x)的点积加上偏压(b),求和通过激活函数。乙状结肠激活函数的输出将为0和1。

func (a *Perceptron) sigmoid(x float64) float64 { //Sigmoid Activation
	return 1.0 / (1.0 + math.Exp(-x))
}

func (a *Perceptron) forwardPass(x []float64) (sum float64) { //Forward Propagation
	return a.sigmoid(dotProduct(a.weights, x) + a.bias)
}

学习算法

学习算法由反向传播和优化两部分组成。

反向传播,简称误差反向传播,是指计算损失函数相对于权重的梯度的算法。然而,这个术语经常被用来指代整个学习算法。

损失函数用来估计我们离期望解有多远。一般来说,回归问题的损失函数是均方误差,分类问题的损失函数是交叉熵。为了简单起见,我们将使用均方误差作为损失函数。另外,我们不会计算MSE,而是直接计算它的梯度。

用链式法则计算损失函数的梯度,损失函数相对于权重和偏差的梯度计算如下。

优化就是选择感知器的最佳权值和偏差,以达到预期的效果。我们选择梯度下降作为优化算法。权值和偏差更新如下,直到收敛。

学习率(α)是一个超参数,用来控制权重和偏差的变化量。但是,我们不会在本教程中使用学习率。

func (a *Perceptron) gradW(x []float64, y float64) []float64 { //Calculate Gradients of Weights
	pred := a.forwardPass(x)
	return  scalarMatMul(-(pred-y)*pred*(1-pred), x)
}

func (a *Perceptron) gradB(x []float64, y float64) float64 { //Calculate Gradients of Bias
	pred := a.forwardPass(x)
	return -(pred - y) * pred * (1 - pred)
}


func (a *Perceptron) train() { //Train the Perceptron for n epochs
	for i := 0; i < a.epochs; i++ {
		dw := make([]float64, len(a.input[0]))
		db := 0.0
		for length, val := range a.input {
			dw = vecAdd(dw, a.gradW(val, a.actualOutput[length]))
			db += a.gradB(val, a.actualOutput[length])
		}
		dw = scalarMatMul(2 / float64(len(a.actualOutput)), dw)
		a.weights = vecAdd(a.weights, dw)
		a.bias += db * 2 / float64(len(a.actualOutput))
	}
}

装配零件

现在让我们用神经网络对以下数据进行训练和预测。数据有三个输入,只有一个输出属于两个类(0和1)。因此,数据可以在我们的单层感知器上训练。

如你所见,输出Y仅依赖于输入X1。现在我们将在上面的数据上训练我们的神经网络,并检查它在1000个时代之后的表现。为了进行预测,我们只需要用测试输入做一个正向传播。

func main() {
	goPerceptron := Perceptron{
		input:        [][]float64{{0, 0, 1}, {1, 1, 1}, {1, 0, 1}, {0, 1, 0}}, //Input Data
		actualOutput: []float64{0, 1, 1, 0},                                   //Actual Output
		epochs:       1000,                                                     //Number of Epoch
	}
	goPerceptron.initialize()
	goPerceptron.train()
	print(goPerceptron.forwardPass([]float64{0, 1, 0}), "\n") //Make Predictions
	print(goPerceptron.forwardPass([]float64{1, 0, 1}), "\n")
}

当我们将预测值与实际值进行比较时,我们可以看到我们训练的单层感知器表现良好。我们已经成功地建立了一个神经网络,并对其进行训练,以产生理想的结果。

接下来是什么?

现在你已经完全从头开始创建了自己的神经网络。下面有几件事你应该试试。

  • 测试自己的数据
  • 尝试除乙状结肠功能外的其他激活功能
  • 计算每个历元后的MSE
  • 尝试除MSE以外的其他错误函数
  • 尝试创建多层感知器

--END--

欢迎大家关注我们的公众号:为AI呐喊(weainahan)

为了帮助更多缺少项目实战的同学入门Python,我们在头条上创建了一个专栏:《7小时快速掌握Pthon核心编程》欢迎大家点击下方链接或者阅读原文进行试看~

相关推荐

了解Linux目录,那你就了解了一半的Linux系统

大到公司或者社群再小到个人要利用Linux来开发产品的人实在是多如牛毛,每个人都用自己的标准来配置文件或者设置目录,那么未来的Linux则就是一团乱麻,也对管理造成许多麻烦。后来,就有所谓的FHS(F...

Linux命令,这些操作要注意!(linux命令?)

刚玩Linux的人总觉得自己在演黑客电影,直到手滑输错命令把公司服务器删库,这才发现命令行根本不是随便乱用的,而是“生死簿”。今天直接上干货,告诉你哪些命令用好了封神!喜欢的一键三连,谢谢观众老爷!!...

Linux 命令速查手册:这 30 个高频指令,拯救 90% 的运维小白!

在Linux系统的世界里,命令行是强大的武器。对于运维小白而言,掌握一些高频使用的Linux命令,能极大提升工作效率,轻松应对各种系统管理任务。今天,就为大家奉上精心整理的30个Linu...

linux必学的60个命令(linux必学的20个命令)

以下是Linux必学的20个基础命令:1.cd:切换目录2.ls:列出文件和目录3.mkdir:创建目录4.rm:删除文件或目录5.cp:复制文件或目录6.mv:移动/重命名文件或目录7....

提高工作效率的--Linux常用命令,能够决解95%以上的问题

点击上方关注,第一时间接受干货转发,点赞,收藏,不如一次关注评论区第一条注意查看回复:Linux命令获取linux常用命令大全pdf+Linux命令行大全pdf为什么要学习Linux命令?1、因为Li...

15 个实用 Linux 命令(linux命令用法及举例)

Linux命令行是系统管理员、开发者和技术爱好者的强大工具。掌握实用命令不仅能提高效率,还能解锁Linux系统的无限潜力,本文将深入介绍15个实用Linux命令。ls-列出目录内容l...

Linux 常用命令集合(linux常用命令全集)

系统信息arch显示机器的处理器架构(1)uname-m显示机器的处理器架构(2)uname-r显示正在使用的内核版本dmidecode-q显示硬件系统部件-(SMBIOS/DM...

Linux的常用命令就是记不住,怎么办?

1.帮助命令1.1help命令#语法格式:命令--help#作用:查看某个命令的帮助信息#示例:#ls--help查看ls命令的帮助信息#netst...

Linux常用文件操作命令(linux常用文件操作命令有哪些)

ls命令在Linux维护工作中,经常使用ls这个命令,这是最基本的命令,来写几条常用的ls命令。先来查看一下使用的ls版本#ls--versionls(GNUcoreutils)8.4...

Linux 常用命令(linux常用命令)

日志排查类操作命令查看日志cat/var/log/messages、tail-fxxx.log搜索关键词grep"error"xxx.log多条件过滤`grep-E&#...

简单粗暴收藏版:Linux常用命令大汇总

号主:老杨丨11年资深网络工程师,更多网工提升干货,请关注公众号:网络工程师俱乐部下午好,我的网工朋友在Linux系统中,命令行界面(CLI)是管理员和开发人员最常用的工具之一。通过命令行,用户可...

「Linux」linux常用基本命令(linux常用基本命令和用法)

Linux中许多常用命令是必须掌握的,这里将我学linux入门时学的一些常用的基本命令分享给大家一下,希望可以帮助你们。总结送免费学习资料(包含视频、技术学习路线图谱、文档等)1、显示日期的指令:d...

Linux的常用命令就是记不住,怎么办?于是推出了这套教程

1.帮助命令1.1help命令#语法格式:命令--help#作用:查看某个命令的帮助信息#示例:#ls--help查看ls命令的帮助信息#netst...

Linux的30个常用命令汇总,运维大神必掌握技能!

以下是Linux系统中最常用的30个命令,精简版覆盖日常操作核心需求,适合快速掌握:一、文件/目录操作1.`ls`-列出目录内容`ls-l`(详细信息)|`ls-a`(显示隐藏文件)...

Linux/Unix 系统中非常常用的命令

Linux/Unix系统中非常常用的命令,它们是进行文件操作、文本处理、权限管理等任务的基础。下面是对这些命令的简要说明:**文件操作类:*****`ls`(list):**列出目录内容,显...