这是我第一次创建神经网络,我决定在 golang 中创建它,这通常不是用于此目的的语言,但是我想从头开始很好地理解它们如何工作仅基本库。
该程序的目标是训练一个神经网络,使其能够将两个数字(1-10)相加。为此,我创建了一个名为 rawai(我能想到的最好的名字)的神经网络类,并给它一个 1 个输入层(大小为 2 的数组)、1 个隐藏层(大小为 2 的数组)和 1 个输出层(大小为 1) 的数组。
权重有2个2d数组,一个是ih(hidden的输入)[2,2],一个是ho,[2,1]。
下面是启动 ai、训练和测试 ai 的代码。您将看到我使用过的几个调试语句,并且非 golang 或其包的任何其他函数将显示在我的 rawai 类的以下代码中。这是由我的 main 函数调用的:
func additionneuralnetworktest() {
nn := newrawai(2, 2, 1, 1/math.pow(10, 15))
fmt.printf("weights ih before: %v\n\nweights ho after: %v\n", nn.weightsih, nn.weightsho)
//train neural network
//
for epoch := 0; epoch < 10000000; epoch++ {
for i := 0; i <= 10; i++ {
for j := 0; j <= 10; j++ {
inputs := make([]float64, 2)
targets := make([]float64, 1)
inputs[0] = float64(i)
inputs[1] = float64(j)
targets[0] = float64(i) + float64(j)
nn.train(inputs, targets)
if epoch%20000 == 0 && i == 5 && j == 5 {
fmt.printf("[training] [epoch %d] %f + %f = %f targets[%f]\n", epoch, inputs[0], inputs[1], nn.outputlayer[0], targets[0])
}
}
}
}
// test neural network
a := rand.intn(10) + 1
b := rand.intn(10) + 1
inputs := make([]float64, 2)
inputs[0] = float64(a)
inputs[1] = float64(b)
prediction := nn.feedforward(inputs)[0]
fmt.printf("%d + %d = %f\n", a, b, prediction)
fmt.printf("weights ih: %v\n\nweights ho: %v\n", nn.weightsih, nn.weightsho)
}
以下是 rawai 文件中的所有代码:
type RawAI struct {
InputLayer []float64 `json:"input_layer"`
HiddenLayer []float64 `json:"hidden_layer"`
OutputLayer []float64 `json:"output_layer"`
WeightsIH [][]float64 `json:"weights_ih"`
WeightsHO [][]float64 `json:"weights_ho"`
LearningRate float64 `json:"learning_rate"`
}
func NewRawAI(inputSize, hiddenSize, outputSize int, learningRate float64) *RawAI {
nn := RawAI{
InputLayer: make([]float64, inputSize),
HiddenLayer: make([]float64, hiddenSize),
OutputLayer: make([]float64, outputSize),
WeightsIH: randomMatrix(inputSize, hiddenSize),
WeightsHO: randomMatrix(hiddenSize, outputSize),
LearningRate: learningRate,
}
return &nn
}
func (nn *RawAI) FeedForward(inputs []float64) []float64 {
// Set input layer
for i := 0; i < len(inputs); i++ {
nn.InputLayer[i] = inputs[i]
}
// Compute hidden layer
for i := 0; i < len(nn.HiddenLayer); i++ {
sum := 0.0
for j := 0; j < len(nn.InputLayer); j++ {
sum += nn.InputLayer[j] * nn.WeightsIH[j][i]
}
nn.HiddenLayer[i] = sum
if math.IsNaN(sum) {
panic(fmt.Sprintf("Sum is NaN on Hidden Layer:\nInput Layer: %v\nHidden Layer: %v\nWeights IH: %v\n", nn.InputLayer, nn.HiddenLayer, nn.WeightsIH))
}
}
// Compute output layer
for k := 0; k < len(nn.OutputLayer); k++ {
sum := 0.0
for j := 0; j < len(nn.HiddenLayer); j++ {
sum += nn.HiddenLayer[j] * nn.WeightsHO[j][k]
}
nn.OutputLayer[k] = sum
if math.IsNaN(sum) {
panic(fmt.Sprintf("Sum is NaN on Output Layer:\n Model: %v\n", nn))
}
}
return nn.OutputLayer
}
func (nn *RawAI) Train(inputs []float64, targets []float64) {
nn.FeedForward(inputs)
// Compute output layer error
outputErrors := make([]float64, len(targets))
for k := 0; k < len(targets); k++ {
outputErrors[k] = targets[k] - nn.OutputLayer[k]
}
// Compute hidden layer error
hiddenErrors := make([]float64, len(nn.HiddenLayer))
for j := 0; j < len(nn.HiddenLayer); j++ {
errorSum := 0.0
for k := 0; k < len(nn.OutputLayer); k++ {
errorSum += outputErrors[k] * nn.WeightsHO[j][k]
}
hiddenErrors[j] = errorSum * sigmoidDerivative(nn.HiddenLayer[j])
if math.IsInf(math.Abs(hiddenErrors[j]), 1) {
//Find out why
fmt.Printf("Hidden Error is Infinite:\nTargets:%v\nOutputLayer:%v\n\n", targets, nn.OutputLayer)
}
}
// Update weights
for j := 0; j < len(nn.HiddenLayer); j++ {
for k := 0; k < len(nn.OutputLayer); k++ {
delta := nn.LearningRate * outputErrors[k] * nn.HiddenLayer[j]
nn.WeightsHO[j][k] += delta
}
}
for i := 0; i < len(nn.InputLayer); i++ {
for j := 0; j < len(nn.HiddenLayer); j++ {
delta := nn.LearningRate * hiddenErrors[j] * nn.InputLayer[i]
nn.WeightsIH[i][j] += delta
if math.IsNaN(delta) {
fmt.Print(fmt.Sprintf("Delta is NaN.\n Learning Rate: %f\nHidden Errors: %f\nInput: %f\n", nn.LearningRate, hiddenErrors[j], nn.InputLayer[i]))
}
if math.IsNaN(nn.WeightsIH[i][j]) {
fmt.Print(fmt.Sprintf("Delta is NaN.\n Learning Rate: %f\nHidden Errors: %f\nInput: %f\n", nn.LearningRate, hiddenErrors[j], nn.InputLayer[i]))
}
}
}
}
func (nn *RawAI) ExportWeights(filename string) error {
weightsJson, err := json.Marshal(nn)
if err != nil {
return err
}
err = ioutil.WriteFile(filename, weightsJson, 0644)
if err != nil {
return err
}
return nil
}
func (nn *RawAI) ImportWeights(filename string) error {
weightsJson, err := ioutil.ReadFile(filename)
if err != nil {
return err
}
err = json.Unmarshal(weightsJson, nn)
if err != nil {
return err
}
return nil
}
//RawAI Tools:
func randomMatrix(rows, cols int) [][]float64 {
matrix := make([][]float64, rows)
for i := 0; i < rows; i++ {
matrix[i] = make([]float64, cols)
for j := 0; j < cols; j++ {
matrix[i][j] = 1.0
}
}
return matrix
}
func sigmoid(x float64) float64 {
return 1.0 / (1.0 + exp(-x))
}
func sigmoidDerivative(x float64) float64 {
return x * (1.0 - x)
}
func exp(x float64) float64 {
return 1.0 + x + (x*x)/2.0 + (x*x*x)/6.0 + (x*x*x*x)/24.0
}
输出的例子是这样的: 正如您所看到的,它慢慢地远离目标并继续这样做。 经过询问、谷歌搜索和搜索这个网站后,我找不到我的错误所在,所以我决定问这个问题。
正确答案
我认为您使用的是 均方误差
并在微分后忘记了 -
。
所以改变:
outputerrors[k] = (targets[k] - nn.outputlayer[k])
致:
outputErrors[k] = -(targets[k] - nn.OutputLayer[k])
以上就是我的神经网络(从头开始)训练,让它离目标更远的详细内容,更多请关注编程网其它相关文章!
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341
软考中级精品资料免费领
- 历年真题答案解析
- 备考技巧名师总结
- 高频考点精准押题
- 资料下载
- 历年真题
193.9 KB下载数265
191.63 KB下载数245
143.91 KB下载数1148
183.71 KB下载数642
644.84 KB下载数2756