如何在NetLogo中实现感知器神经网络奇偶数字识别模型
在NetLogo中实现感知器神经网络判断数字奇偶
没问题!这个奇偶判断任务其实特别适合用单层感知器来做——毕竟奇偶是线性可分的问题,根本不需要复杂的多层网络。下面我一步步给你拆解怎么在NetLogo里实现:
核心思路先理清楚
我们的目标是让感知器接收0-9的数字,输出它是偶数(Pair)还是奇数(Impair)。方案很直接:
- 输入:0-9之间的单个整数
- 输出:1代表偶数,0代表奇数
- 感知器结构:单个输入节点 + 权重 + 偏置 + 阶跃激活函数
具体代码实现
1. 定义全局变量
先声明感知器的核心参数:
globals [ weight ; 感知器的输入权重 bias ; 偏置项,用来调整决策边界 learning-rate ; 学习率,控制参数更新的步长 ]
2. 初始化感知器
启动时随机初始化权重和偏置,设置合适的学习率:
to setup set learning-rate 0.1 ; 随机初始化权重和偏置(范围-1到1),让模型从随机状态开始学习 set weight random-float 2 - 1 set bias random-float 2 - 1 print "感知器参数已初始化,准备开始训练!" end
3. 定义激活函数
用阶跃函数做二分类判断,超过阈值(0)输出1,否则输出0:
to-report activate [net-input] ; 阶跃函数:输入>0返回1(偶数),否则返回0(奇数) ifelse net-input > 0 [ report 1 ] [ report 0 ] end
4. 预测函数(前向传播)
计算输入的加权和加偏置,再经过激活函数得到预测结果:
to-report predict [number] let net-input (number * weight) + bias report activate net-input end
5. 训练过程(反向更新)
用监督学习的方式,遍历0-9的所有数字,根据误差调整权重和偏置:
to train repeat 100 [ ; 训练100轮,足够让模型收敛到正确的参数 ; 遍历所有训练样本(0-9) foreach [0 1 2 3 4 5 6 7 8 9] [ let current-num ? ; 确定当前数字的真实标签:偶数=1,奇数=0 let true-label ifelse-value (current-num mod 2 = 0) [1] [0] ; 获取模型的预测结果 let pred-label predict current-num ; 计算误差:真实值 - 预测值 let error true-label - pred-label ; 根据感知器学习规则更新权重和偏置 set weight weight + (learning-rate * error * current-num) set bias bias + (learning-rate * error) ] ] print "训练完成!现在可以测试模型啦~" end
6. 测试模型
写一个测试函数,输入0-9的数字,输出预测结果和真实结果对比:
to test [input-number] ; 先校验输入范围 if input-number < 0 or input-number > 9 [ print "请输入0-9之间的整数哦!" stop ] let pred-result predict input-number let pred-label ifelse-value (pred-result = 1) ["偶数(Pair)" "奇数(Impair)"] let true-label ifelse-value (input-number mod 2 = 0) ["偶数(Pair)" "奇数(Impair)"] print (word "输入数字:" input-number) print (word "模型预测:" pred-label) print (word "真实结果:" true-label) print "------------------------" end
界面设置建议
在NetLogo的界面里添加以下控件:
- 一个
setup按钮,绑定到setup过程 - 一个
train按钮,绑定到train过程 - 一个输入框(类型为数字),命名为
test-number - 一个
test按钮,绑定到test test-number过程
这样你就能点击按钮初始化、训练,然后输入数字测试啦!
额外小优化(可选)
如果想模拟更贴近真实手写数字的输入场景,可以把数字转换成二进制特征(比如4位二进制)作为输入。比如数字5是101,对应输入列表[1,0,1,0],这时候权重需要改成列表类型,计算加权和的时候用sum map * input-list weight-list就行,训练逻辑和单输入版本基本一致,只是输入维度变多了。
内容的提问来源于stack exchange,提问作者joekim
相关产品推荐
相关产品推荐

