动手造轮子自己实现人工智能神经网络(ANN)解决鸢尾花分类问题Golang1.18实现

科技资讯 投稿 6300 0 评论

动手造轮子自己实现人工智能神经网络(ANN)解决鸢尾花分类问题Golang1.18实现

机器学习可以解决什么问题

机器学习可以帮助我们解决两大类问题:回归问题和分类问题,它们的主要区别在于输出变量的类型和预测目标的不同。

在分类问题中,输出变量是离散值,预测目标是将样本划分到不同的类别中。例如,预测邮件是否是垃圾邮件、预测图像中的物体类别等都是分类问题。通常使用分类模型,如逻辑回归、决策树分类、支持向量机、神经网络分类等来解决这类问题。分类问题的评估指标通常是准确率、精度(Precision)、召回率(Recall)等。

同时,机器学习输入的特征参数和输出的预期结果必须有逻辑相关性,什么意思?比如说我们想预测房价,结果特征参数输入了很多没有任何逻辑相关性的数据,比如历年水稻的出产率,这就是没有逻辑相关性的数据,这样的问题再怎么调参也是无法通过机器学习来解决的。

因为,稍微有点投资经验的人都知道,股票的历史数据和未来某个时间点或者某个时间段的实际价格,并不存在因果关系,尤其像A股市场这种可被操控的黑盒环境,连具体特征都是隐藏的,或者说特征是什么都是未知的,你以为的特征只是你以为的,并不是市场或者政策以为的,所以你输入之前十年或者二十年的历史股票数据,你让它预测,就是在搞笑,机器学习没法帮你解决此类问题。

鸢尾花分类问题

鸢尾花分类问题是一个经典的机器学习问题,也是神经网络入门的常用案例之一。它的目标是通过鸢尾花的花萼长度、花萼宽度、花瓣长度和花瓣宽度这四个特征来预测鸢尾花的品种,分为三种:山鸢尾(Iris Setosa)、变色鸢尾(Iris Versicolour)和维吉尼亚鸢尾(Iris Virginica)。

在这个案例中,我们使用了一个包含一个隐藏层的神经网络,它的输入层有4个神经元,代表鸢尾花的4个特征;隐藏层有3个神经元;输出层有3个神经元,分别代表3种鸢尾花的品种:

输入层:输入层接收外部输入信号,是神经网络的起点。它的神经元数量与输入特征的数量相同,每个神经元代表一个输入特征。输入层的主要作用是将外部输入转换为神经网络内部的信号。

输出层:输出层是神经网络的终点,它的神经元数量通常与问题的输出数量相同。每个神经元代表一个输出结果,输出层的主要作用是将隐藏层处理后的信号进行进一步处理,并将最终的结果输出。

定义神经网络结构体

在开始训练之前,我们先定义一些需要的结构体和函数:

// neuralNet contains all of the information  
// that defines a trained neural network.  
type neuralNet struct {  
	config  neuralNetConfig  
	wHidden *mat.Dense  
	bHidden *mat.Dense  
	wOut    *mat.Dense  
	bOut    *mat.Dense  
}  
  
// neuralNetConfig defines our neural network  
// architecture and learning parameters.  
type neuralNetConfig struct {  
	inputNeurons  int  
	outputNeurons int  
	hiddenNeurons int  
	numEpochs     int  
	learningRate  float64  
}

这里neuralNet是神经网络结构体,同时定义输入、隐藏和输出层神经元的配置。

func newNetwork(config neuralNetConfig *neuralNet {  
        return &neuralNet{config: config}  
}

这里返回神经网络的指针。

// sigmoid implements the sigmoid function  
// for use in activation functions.  
func sigmoid(x float64 float64 {  
        return 1.0 / (1.0 + math.Exp(-x  
}  
  
// sigmoidPrime implements the derivative  
// of the sigmoid function for backpropagation.  
func sigmoidPrime(x float64 float64 {  
    return sigmoid(x * (1.0 - sigmoid(x  
}

实现反向传播

反向传播是指在前向传播之后,计算神经网络误差并将误差反向传播到各层神经元中进行参数(包括权重和偏置)的更新。在反向传播过程中,首先需要计算网络的误差,然后通过链式法则将误差反向传播到各层神经元,以更新每个神经元的权重和偏置。这个过程也被称为“反向梯度下降”,因为它是通过梯度下降算法来更新神经网络参数的。

1 初始化权重和偏置(例如,随机初始化)。

3 将输出与正确输出进行比较,以获取误差。

5 将变化通过神经网络进行反向传播。

在步骤3-5中,我们将利用随机梯度下降(SGD)来确定权重和偏置的更新:

// train trains a neural network using backpropagation.  
func (nn *neuralNet train(x, y *mat.Dense error {  
  
    // Initialize biases/weights.  
    randSource := rand.NewSource(time.Now(.UnixNano(  
    randGen := rand.New(randSource  
  
    wHidden := mat.NewDense(nn.config.inputNeurons, nn.config.hiddenNeurons, nil  
    bHidden := mat.NewDense(1, nn.config.hiddenNeurons, nil  
    wOut := mat.NewDense(nn.config.hiddenNeurons, nn.config.outputNeurons, nil  
    bOut := mat.NewDense(1, nn.config.outputNeurons, nil  
  
    wHiddenRaw := wHidden.RawMatrix(.Data  
    bHiddenRaw := bHidden.RawMatrix(.Data  
    wOutRaw := wOut.RawMatrix(.Data  
    bOutRaw := bOut.RawMatrix(.Data  
  
    for _, param := range [][]float64{  
        wHiddenRaw,  
        bHiddenRaw,  
        wOutRaw,  
        bOutRaw,  
    } {  
        for i := range param {  
            param[i] = randGen.Float64(  
        }  
    }  
  
    // Define the output of the neural network.  
    output := new(mat.Dense  
  
    // Use backpropagation to adjust the weights and biases.  
    if err := nn.backpropagate(x, y, wHidden, bHidden, wOut, bOut, output; err != nil {  
        return err  
    }  
  
    // Define our trained neural network.  
    nn.wHidden = wHidden  
    nn.bHidden = bHidden  
    nn.wOut = wOut  
    nn.bOut = bOut  
  
    return nil  
}

接着实现具体的反向传播逻辑:

// backpropagate completes the backpropagation method.  
func (nn *neuralNet backpropagate(x, y, wHidden, bHidden, wOut, bOut, output *mat.Dense error {  
  
    // Loop over the number of epochs utilizing  
    // backpropagation to train our model.  
    for i := 0; i < nn.config.numEpochs; i++ {  
  
        // Complete the feed forward process.  
        hiddenLayerInput := new(mat.Dense  
        hiddenLayerInput.Mul(x, wHidden  
        addBHidden := func(_, col int, v float64 float64 { return v + bHidden.At(0, col }  
        hiddenLayerInput.Apply(addBHidden, hiddenLayerInput  
  
        hiddenLayerActivations := new(mat.Dense  
        applySigmoid := func(_, _ int, v float64 float64 { return sigmoid(v }  
        hiddenLayerActivations.Apply(applySigmoid, hiddenLayerInput  
  
        outputLayerInput := new(mat.Dense  
        outputLayerInput.Mul(hiddenLayerActivations, wOut  
        addBOut := func(_, col int, 

编程笔记 » 动手造轮子自己实现人工智能神经网络(ANN)解决鸢尾花分类问题Golang1.18实现

赞同 (35) or 分享 (0)
游客 发表我的评论   换个身份
取消评论

表情
(0)个小伙伴在吐槽