关于人工智能:人工智能机器学习底层原理剖析人造神经元您一定能看懂通俗解释把AI黑话转化为白话文

4次阅读

共计 5574 个字符,预计需要花费 14 分钟才能阅读完成。

依照固有思维形式,人们总以为人工智能是一个莫测高深的行业,这个行业的人都是高智商人群,无论是写文章还是和人讲话,总是守口如瓶,接着就是蹦出一些“高级”词汇,什么“神经网络”,什么“卷积神经”之类,教人半懂不懂的。尤其 ChatGPT 的风行一时,更加“神话”了这个行业,用鲁迅学生形容诸葛武侯的话来讲:“多智而近妖”。

事实上,依据二八定理,和别的行业一样,人工智能行业内真正顶尖的蠢才也就是 20%,他们具备真正的行业颠覆能力,能够搞出像 ChatGPT 这种“工业革命”级别的产品,而剩下的 80% 也不过就是普通人,每天的工作和咱们这些人一样,干燥且乏味,而之所以会呈现相似“行业壁垒”的景象,是因为这个行业的“黑话”太多了,导致个别人听不懂,所谓“黑话”能够了解为行业术语,搞清楚了这些所谓的行业术语,你会发现,所谓的“人工智能”,不过也就是个“套路活儿”。

本次咱们试图应用“白话文”来描摹人工智能机器学习的底层逻辑,并且通过 Golang1.18 来实现人造神经元的原理。

人造神经元 Neural

当初业内比拟风行的,比方 Transformer 模型、GPT 模型、深度学习、强化学习、卷积神经网络等等,无论听起来如许高端大气上档次,说出大天去,它也是神经网络架构,换句话说它们的底层都一样,类比的话,就像汽车行业,无论是汽油驱动还是电驱动、三缸发动机还是六缸发动机、单电机还是双电机,混合能源还是插混能源,无论汽车主机厂怎么吹牛逼,无论车评人怎么疯狂恰饭,厂商造出来的车最终还是一个最根本的汽车架构,说白了就是一个底盘四个轮儿,你再牛逼,你也逃不出这个根本架构。

所以说,机器学习的根本架构是神经网络架构,神经网络由大量的人工神经元组成,它们联结之后就能够进行所谓的“机器学习”。所以,必须搞清楚什么是神经元,能力弄懂神经网络。

神经元是神经网络架构中最渺小的单位,也是最小的可训练单位,一个根本的神经元构造是上面这样的:

毋庸讳言,大多数人看见这个基本上都会霎时放弃,数学公式几乎就是开发界的洪水猛兽,其劝退能力堪比艾尔登法环中的大树守卫,咱们的机器学习之旅还没开始,就曾经完结了。

那么咱们把这个玩意儿翻译成大多数人能看懂的样子:f(sum( x*w) + b )

x 代表输出的数据,w 代表权重,sum 代表求和,b 代表偏差,f 代表激活函数,最初这个公式运行的后果,就是机器学习的后果。

简略往外头套点数据,比方我心愿机器学习的后果是 10,那么,x、w、和 b 别离应该是什么能力让后果变为 10 呢?如果 x=2 w=4 b = 2 就是咱们想要的后果。这也就是最根本的线性回归,咱们只解决一个维度的数据,因为后果曾经不言而喻了,咱们曾经不须要机器学习了,因为靠猜也能猜出来后果是什么。

然而生产环境中,x 并非是单维度,而是多维度的,比方 x1、x2、x3….. 组成的矩阵,但无论是多维度还是单维度,计算公式用的还是一样的,每一个 x 对应一个权重 w,所以是 xn*wn。

说白了,x 就是一个多维特色,类比的话,如果咱们想让电脑智能识图,比方辨认一只猫,那么 x 就是猫的特色,比方状态、色彩、眼睛、叫声等等,作为多维度的输出特色 x,喂给电脑,让电脑给出辨认后果,这就是简略的机器学习解决分类问题。

这里须要留神的是,x 作为特征参数,并不是越多越好,而是特色越显著越好,举个例子,你想让 AI 去辨认鲁迅的文章,那提供的特色最好应该具备鲁迅文章的特点,而不是全量输出,因为鲁迅就算再“鲁迅”,他写的文字也会和他人反复,也就是说并不是每句话都是他独有的,如果把他所有的文章都喂给电脑,可能就会产生“噪声”,影响机器学习的后果。

另外应该晓得的是,x 参数特色并不是咱们认为的单词或者汉字,而是一串单精度区间在 0 - 1 之间的浮点数字,也就是所谓的“向量”,因为只有数字能力套着神经元公式进行计算。

所以所有的文本特色在进行神经元计算之前,必须通过一些办法进行“向量化”操作。说白了就是把汉字转化为数字,就这么简略。

另外这也就证实了,电脑真的没有思维,它不了解什么是猫,或者谁是鲁迅,它就是在进行计算,而已。

随后是 w,w 指的是权重,权重是指神经元接管到的输出值的重要性,这些输出值通过乘以对应的权重,被加权求和作为神经元的输出。权重值越大,示意该输出在神经元的输入中所占的比重越大。说白了,猫的所有特色的权重并不是对立的,比方黑夜里忽然一个货色跳了进去,你怎么判断它是什么物种?很显著,一声“喵呜”咱们就能够立即判定这是一只猫,所以叫声特色的权重肯定大于其余特色的权重。

最初是 b,也就是偏差 (bias),偏差通常是一个实数,与神经元的权重一样,也是通过训练神经网络而调整的参数。偏差的作用是在神经元的输出上减少一个常量,以调整神经元的激活阈值。如果没有偏差,那么神经元的激活函数将仅仅取决于加权和的值,而无奈产生任何偏移。

说白了,b 就是让 x * w 的值更活一点,让它不是“死”的数。

最初说说 f 也就是激活函数,激活函数通常具备非线性的个性,这使得神经网络可能拟合非线性的简单函数,从而进步其性能和准确度。

说白了,如果没有激活函数,咱们的权重计算就是“线性”的,什么叫线性?如果把 x 特色从 1 开始输出,始终到 100,而后将计算结果绘制成图:

咱们会发现计算结果是一根直线,这显然不合乎客观规律,更合乎生物特色的状态应该是“曲线”,所以说白了,激活函数 f 的作用就是把“直线”变成“曲线”。

最初,咱们把神经元公式革新成不便咱们了解的模式:冀望后果 = 激活函数 (求和 ( 特色 * 权重) + 偏差 )。

如果用代码实现这个公式:

func neuron(inputs []float64, weights []float64, bias float64) float64 {if len(inputs) != len(weights) {panic("inputs and weights must have the same length")  
    }  
    sum := bias  
    for i := 0; i < len(inputs); i++ {sum += inputs[i] * weights[i]  
    }  
    return sum  
}

这个函数接管两个长度雷同的浮点数数组 inputs 和 weights,以及一个偏置值 bias。它通过将每个输出值乘以其对应的权重,加上偏置值,失去神经元的加权和。最初,函数返回这个加权和作为神经元的输入值。

应用这个函数时,能够将输出数据和权重作为参数传递给它。例如,假如咱们有一个二分类问题,输出数据有两个特色:x1 和 x2,并且咱们有一个蕴含两个权重和一个偏置的神经元。那么能够这样调用神经元公式:

inputs := []float64{x1, x2}  
weights := []float64{w1, w2}  
bias := b  
output := neuron(inputs, weights, bias)

这里返回神经元的输入值,所以,谁说学习人工智能必须得用 Python?咱们就骄傲地应用 Golang。

机器学习,到底怎么学习

机器学习的过程就是上文中神经元公式的应用过程,第一步收集所有的特色数据,而后进行权重调配,最初向量化操作,把文本数据转换为计算机能计算的浮点数,随后加权求和,之后加一个偏差 (bias),最初过一下激活函数,最终失去一个冀望后果,就完事了。

难吗?不难,普通人连猜带蒙也能做。

但事实上,这只是原理,也就是最根本的货色,个别人都能把握,比方打篮球,规定非常简单,外围就是运球和投篮,无反抗下小学生也能霎时把握,但小学生没法去打 NBA 级别的较量,因为很多高端的篮球技术是构筑于运球和投篮的,须要经久不息的练习和本身天才的加成,所以全世界能打 NBA 的就那么几百人,而已。

同理,机器学习的过程也并非如此简略,通过特色输出,通过神经元公式,失去的后果真的肯定是咱们所冀望的后果吗?

其实未必,机器学习还包含两个极其重要的概念:前向流传和反向流传。

前向流传是指将输出数据从神经网络的输出层传递到输入层的过程。在前向流传过程中,输出数据通过神经网络的每一层,每个神经元都会对其进行肯定的加权和激活函数计算,最终失去输入层的输入值。这个过程也被称为“正向流传”,因为数据是从输出层顺次向前流传到输入层。

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

说白了,前向流传就是由特色到后果的过程,反向流传则是逆运算,用后果反推过程。

回到分类问题,咱们输出了猫的特色和特色权重,通过计算,后果未必是猫,可能是狗,或者是耗子,也可能是别的什么货色,但这不重要,重要的是咱们须要拿到一个后果的误差,这个误差越小越好,而反向流传就是帮咱们推算误差到底有多大的办法。

而误差的大小就取决于特色的输出,导致机器学习后果谬误的本源是参数,此时,咱们须要调整参数的输出,从而减小误差值,这也就是人工智能行业从业人员常常说的“调参”。

比方,咱们冀望后果是猫,后果计算机返回狗,那么调整参数,后果返回熊猫,那么就阐明调大发了,持续调整,直到计算机返回后果:猫。

在 Golang1.18 中,能够通过以下代码实现反向流传:

func backpropagation(inputs []float64, targets []float64, network *Network, learningRate float64) {  
    // 1. 前向流传,计算每个神经元的输入值  
    outputs := feedforward(inputs, network)  
  
    // 2. 计算输入层的误差  
    outputErrors := make([]float64, len(outputs))  
    for i := range outputs {outputErrors[i] = outputs[i] - targets[i]  
    }  
  
    // 3. 反向流传误差,计算每个神经元的误差值  
    for i := len(network.layers) - 1; i >= 0; i-- {layer := network.layers[i]  
        errors := make([]float64, len(layer.neurons))  
  
        // 3.1. 计算神经元的误差值  
        if i == len(network.layers)-1 {  
            // 输入层的误差  
            for j := range layer.neurons {errors[j] = outputErrors[j] * sigmoidPrime(layer.neurons[j].output)  
            }  
        } else {  
            // 暗藏层的误差  
            for j := range layer.neurons {  
                errorSum := 0.0  
                nextLayer := network.layers[i+1]  
                for k := range nextLayer.neurons {errorSum += nextLayer.neurons[k].weights[j] * nextLayer.neurons[k].error  
                }  
                errors[j] = errorSum * sigmoidPrime(layer.neurons[j].output)  
            }  
        }  
  
        // 3.2. 将误差值保留到神经元中  
        for j := range layer.neurons {layer.neurons[j].error = errors[j]  
        }  
    }  
  
    // 4. 更新神经网络的权重和偏置  
    for i := range network.layers {layer := network.layers[i]  
  
        // 4.1. 更新权重  
        for j := range layer.neurons {for k := range layer.neurons[j].weights {  
                if i == 0 {  
                    // 输出层的权重  
                    layer.neurons[j].weights[k] -= learningRate * layer.neurons[j].error * inputs[k]  
                } else {  
                    // 暗藏层和输入层的权重  
                    prevLayer := network.layers[i-1]  
                    layer.neurons[j].weights[k] -= learningRate * layer.neurons[j].error * prevLayer.neurons[k].output  
                }  
            }  
  
            // 4.2. 更新偏置  
            layer.neurons[j].bias -= learningRate * layer.neurons[j].error  
        }  
    }  
}

这个函数接管输出数据 inputs、指标数据 targets、神经网络 network 以及学习率 learningRate 作为参数。它首先调用 feedforward 函数进行前向流传,计算每个神经元的输入值。而后,它计算输入层的误差,通过误差反向流传,计算每个神经元的误差值,并将其保留到神经元中。

接下来,函数依据误差值和学习率更新神经网络的权重和偏置。在更新权重时,须要依据神经元所在的层来抉择更新的权重类型(输出层、暗藏层或输入层),而后依据误差值和输出数据或上一层神经元的输入值来更新权重。在更新偏置时,只须要依据误差值和学习率来更新即可。

总的来说,这个函数实现了反向流传的所有步骤,能够用于训练神经网络并进步其准确度和性能。

结语

小道不过三俩句,说破不值半文钱,所谓人工智能机器学习就这么回事,没必要神话,也毋庸贬斥,类比的话,就像餐饮行业的厨师岗,所谓做菜,底层原理是什么?就是食材和火候,把握了做菜的底层原理,就能做出好菜,其余的,比方刀工、色彩等等,不过就是精益求精的货色,而已。

所以机器学习就是做菜,做进去的货色可能不尽如人意,就得不停地调整食材的搭配和火候的大小,所谓机器学习的最重要技巧,其实是特色的提取以及参数的调整,所谓大道至简,必由之路。

正文完
 0