python搭建 ADLINE 网络判断男女

小记

f ( x ) = σ ( w x + b ) f(x)=\sigma(wx+b) f(x)=σ(wx+b) 该模型叫做ADLINE(Adative Linear Neuron,自适应线性神经元) ,1960年发明的

2022.4.8 仿照 张觉非的《用Python实现深度学习框架》的第二章搭建

题目

训练一个模型, 给出一个人的身高、体重和体脂率,判断男女。

判断思路

男性的label=1,女性label=-1,

得出的predict,predict=1判断为男性,predict=-1判断为女性

搭建难点

  1. 树形结构,层层递归的理解

  2. 反向传播时,计算每个父节点对子节点的雅克比矩阵,这时矩阵求导是个难点。比如C=step(A),求C对A的导数, C=AB, C对A对导数。

注意事项

  1. 每次训练完毕后要把jacobi和value置为None,因为如果不置None,就不会去计算新的值

  2. 矩阵乘法顺序,参见机器学习中的https://www.cnblogs.com/pinard/p/10825264.html矩阵向量求导(四) 矩阵向量求导链式法则 - 刘建平Pinard - 博客园 (cnblogs.com) 。
    z = f ( y ) , y = x w , ∂ z ∂ x = ∂ z ∂ y w T , ∂ z ∂ w = x T ∂ z ∂ y , (对左边求导,它的导数放在右边;对右边求导,它的导数放在左边) z=f(y),y=xw,\ \frac{\partial z}{\partial x}=\frac{\partial z}{\partial y}w^T, \\ \frac{\partial z}{\partial w}=x^T\frac{\partial z}{\partial y}, \\(对左边求导,它的导数放在右边;对右边求导,它的导数放在左边) z=f(y),y=xw, ∂x∂z​=∂y∂z​wT,∂w∂z​=xT∂y∂z​,(对左边求导,它的导数放在右边;对右边求导,它的导数放在左边)

代码框架

代码

main.py

import numpy as np
from icecream import ic
import node
import ope
import loss
from graph import  default_graphdef make_test():# 生产测试数据m_h = np.random.normal(171, 6, 500)f_h = np.random.normal(168, 5, 500)m_w = np.random.normal(70, 10, 500)f_w = np.random.normal(57, 8, 500)m_bfrs = np.random.normal(16, 2, 500)f_bfrs = np.random.normal(22, 2, 500)m_labels = [1] * 500f_labels = [-1] * 500train_set = np.array([np.concatenate((m_h, f_h)),np.concatenate((m_w, f_w)),np.concatenate((m_bfrs, f_bfrs)),np.concatenate((m_labels, f_labels))]).Tnp.random.shuffle(train_set)return  train_setif __name__=='__main__':train_set=make_test()x=node.Variable(shape=(3,1))w=node.Variable(shape=(1,3))b=node.Variable(shape=(1,1))label=node.Variable(shape=(1,1))w.set_value(np.mat(np.random.normal(0,0.001,(1,3))))b.set_value(np.mat(np.random.normal(0,0.001,(1,1))))y=ope.Add(ope.MatMul(w,x),b)loss=loss.PerceptionLoss(ope.MatMul(label,y))predict=ope.Step(y)learning_rate=0.001for epoch in range(100):for data in train_set:# 输入数据x.set_value(np.mat(data[:-1]).T)label.set_value(np.mat(data[-1]))loss.forward()w.backward(loss)b.backward(loss)# 想优化的结点都是标量结点,即都是1*n,w.set_value(w.value - learning_rate * w.jacobi.T.reshape(w.shape()))b.set_value(b.value - learning_rate * b.jacobi.T.reshape(b.shape()))default_graph.clear_jacobi()  #要清理每一次的雅可比矩阵,否则递归时会因为雅可比矩阵含有值而不重新计算if epoch%10==0:pred = []for data in train_set:# 输入数据x.set_value(np.mat(data[:-1]).T)label.set_value(np.mat(data[-1]))predict.forward()pred.append(predict.value[0, 0])pred = np.array(pred) * 2 - 1accuracy = (train_set[:, -1] == pred).astype(np.int).sum() / len(train_set)print("训练次数为:",epoch,"时,准确率为:",accuracy)ic(epoch,accuracy)

node.py

# node.py
from  graph import default_graph
import numpy as np
from abc import ABC, abstractmethod
from icecream import icclass Node(object):def __init__(self,*parents):#把结点加入默认的图self.graph=default_graphself.graph.add_node(self)#性质self.parents=list(parents)self.children=[]self.value=Noneself.jacobi=Nonefor parent in self.parents:parent.children.append(self)@abstractmethoddef compute(self):"""抽象方法,根据父节点的值计算本节点的值在前向传播时使用"""pass@abstractmethoddef get_jacobi(self,parent):# ic(type(self))"""抽象方法,计算本节点对某个父节点的雅可比矩阵在反向传播时用"""pass#以下为node的通用函数def dimension(self):assert self.value is not Nonereturn self.value.shape[0]*self.value.shape[1]def shape(self):assert self.value is not Nonereturn  self.value.shapedef clear_jacobi(self):self.jacobi=Nonedef reset_value(self, recursive=True):self.value = Noneif recursive:for child in self.children:child.reset_value()def forward(self):for parent in self.parents:if parent.value is None:parent.forward()self.compute()def backward(self,result):if self.jacobi is None:if self is result:self.jacobi = np.mat(np.eye(self.dimension()))else:self.jacobi = np.mat(np.zeros((result.dimension(), self.dimension())))for child in self.children:# 这里有个乘法顺序要注意,因为都是对w求导且w在左边(y=wx+b),故上个结点对该结点的导数是在右边的if child.value is not None:self.jacobi += child.backward(result) * child.get_jacobi(self)return self.jacobiclass Variable(Node):def __init__(self,shape,**kwargs):Node.__init__(self, **kwargs)self.size=shapedef set_value(self,value):assert isinstance(value, np.matrix)# 注意Variable的形状是在定义的时候就设定好的,故而使用self.sizeassert self.size ==value.shapeself.reset_value()self.value=value

ope.py

from node import Node
import numpy as np
from icecream import ic
class Operator(Node):passclass Add(Operator):def compute(self):assert self.parents is not Noneself.value=np.mat(np.zeros(self.parents[0].shape()))for parent in self.parents:assert self.shape()==parent.shape()self.value+=parent.valuedef get_jacobi(self, parent):return np.identity(parent.dimension())class MatMul(Operator):def compute(self):assert len(self.parents)==2assert self.parents[0].shape()[1] ==self.parents[1].shape()[0]self.value=self.parents[0].value *self.parents[1].valuedef get_jacobi(self,parent):# 矩阵乘法的雅可比矩阵在书41页zeros = np.mat(np.zeros((self.dimension(), parent.dimension())))if parent is self.parents[0]:return fill_diagonal(zeros, self.parents[1].value.T)elif parent is self.parents[1]:"""原理比较复杂,见书P44,最后是通过重排列行和列的索引方式实现的"""jacobi = fill_diagonal(zeros, self.parents[0].value)row_sort = np.arange(self.dimension()).reshape(self.shape()[::-1]).T.ravel()col_sort = np.arange(parent.dimension()).reshape(parent.shape()[::-1]).T.ravel()return jacobi[row_sort, :][:, col_sort]class Step(Operator):def compute(self):assert len(self.parents)==1self.value=np.mat(np.where(self.parents[0].value>0.0,1.0,0.0))def get_jacobi(self,parent):"""因为在这个代码离,Step只用于得到预测值,故而不用对其反向传播求导就不算了"""pass# 一些函数补充def fill_diagonal(to_be_filled, filler):"""将 filler 矩阵填充在 to_be_filled 的对角线上"""assert to_be_filled.shape[0]/filler.shape[0] == to_be_filled.shape[1]/filler.shape[1]h,w=filler.shapen=to_be_filled.shape[0]//filler.shape[0]for i in range(n):to_be_filled[i*h:(i+1)*h,i*w:(i+1)*w]=fillerreturn to_be_filled

loss.py

from node import Node
import numpy as np
from icecream import ic
class LossFunction(Node):passclass PerceptionLoss(LossFunction):"""感知机损失,输入为正时为0,输入为负时为输入的相反数"""def compute(self):x=self.parents[0].valueself.value=np.mat(np.where(x>=0.0, 0.0, -x))def get_jacobi(self,parent):"""雅克比矩阵为对角阵,每个对角线元素对应一个父节点元素。若父节点元素大于0,则相应对角线元素(偏导数)为0,否则为-1。"""diag = np.where(parent.value >= 0.0, 0.0, -1)return np.diag(diag.ravel())

graph.py


class Graph():def __init__(self):self.nodes=[]def clear_jacobi(self):for node in self.nodes:node.clear_jacobi()def add_node(self,node):self.nodes.append(node)# 全局默认计算图
default_graph = Graph()

训练结果

训练次数为: 10 时,准确率为: 0.831
训练次数为: 20 时,准确率为: 0.929
训练次数为: 30 时,准确率为: 0.912
训练次数为: 40 时,准确率为: 0.938
训练次数为: 50 时,准确率为: 0.939
训练次数为: 60 时,准确率为: 0.941
训练次数为: 70 时,准确率为: 0.942
训练次数为: 80 时,准确率为: 0.93
训练次数为: 90 时,准确率为: 0.93

python搭建 ADLINE 网络判断男女相关推荐

  1. Python实现手机号自动判断男女性别

    python实现手机号男女性别判断 如果你觉得有用欢迎关注我吧 本文性别判断主要依靠airtest中的自动化测试实现 通过自动对比支付宝页面男女图像,从而实现男女判断 代码如下: 男女判断函数: // ...

  2. python判别性别的代码_学习文章—(Python实践)Python实现手机号自动判断男女性别...

    作者:西西里传说 来源:CSDN博客 链接:https://blog.csdn.net/qq_15687823/article/details/103645268 如果你觉得有用欢迎关注我吧 本文性别 ...

  3. Python搭建UDP网络通信模型,制作一个简单的私人聊天器~

    互联网的本质是什么? 其实就是信息的交换. 就比如我们常用的QQ.微信等. 那么如何将自己的信息发送到其他人的电脑上呢? 那就需要借助网络模型来完成这样的事情了. 今天就带领大家使用UDP网络模型来完 ...

  4. 使用pytorch搭建MLP多层感知器分类网络判断LOL比赛胜负

    使用pytorch搭建MLP多层感知器分类网络判断LOL比赛胜负 1. 数据集 百度网盘链接,提取码:q79p 数据集文件格式为CSV.数据集包含了大约5万场英雄联盟钻石排位赛前15分钟的数据集合,总 ...

  5. 从零开始用Python搭建Socket服务器(初篇)

    本文假设你学过Python方面的知识 文章目录 前言 Socket 1.基本结构 2.高级应用 前言 如何加密自己的信息?如何基本安全的发送自己的信息? Python的Socket库搭建的服务器可以完 ...

  6. python从零基础到项目实战怎么样-Python 3.x网络爬虫从零基础到项目实战

    ● 案例完整 本书中的所有案例都是通过"理论讲解 + 环境搭建 + 完整代码及分析 + 运行结果"这种完善的结构进行讲解的.此外,复杂的案例配有项目结构图,有难度的案例还分析了底层 ...

  7. 区块链实践(一) 以太坊网络+geth搭建私有网络实战

    一.以太网网络  理解以太坊 PrivateNetwork 先要理解以太坊的两种官方网络, 目前以太坊官方提供了两种网 生产环境网络 测试网络 TestNet **  1 以太坊生产网络 以太坊的生产 ...

  8. 从零开始用Python搭建超级简单的点击率预估模型

    全文共2080个字,24张图,预计阅读时间14分钟. 点击率预估模型 前言 本篇是一个基础机器学习入门篇文章,帮助我们熟悉机器学习中的神经网络结构与使用. 日常中习惯于使用Python各种成熟的机器学 ...

  9. 学习C++项目—— 搭建多线程网络服务框架,性能测试(并发性能测试,业务性能测试,客户端响应时间测试,网络带宽测试)

    学习计算机网络编程 一.思路和学习方法   本文学习于:C语言技术网(www.freecplus.net),在 b 站学习于 C 语言技术网,并加以自己的一些理解和复现,如有侵权会删除.   接下来对 ...

最新文章

  1. Android CheckBox 修改选择框
  2. java显示位图_java – 大图标位图在通知中显示为白色方块?
  3. 基于K-Means聚类算法的主颜色提取
  4. PHP 打印调用堆栈信息
  5. 通过js获取元素css3的transform rotate旋转角度方法
  6. java二嗨租车项目_JAVA第二季项目实战———答答租车系统代码
  7. 带权图的最短路径算法(Dijkstra)实现
  8. 如何设计 React 代码结构?
  9. 排序算法之一 冒泡排序(C++版本)
  10. PSpice应用 软件安装和B-1
  11. Android支持库AndroidX和support-v4、appcompat-v7的前世今生!
  12. 【Sentry使用】自定义transaction
  13. 一文读懂Nabla算子
  14. 子载波间隔与符号长度
  15. vue2之v-for详解
  16. vulnhub靶场之 LordOfTheRoot_1.0.1
  17. 韩国PAYWAVE认证之技术篇2
  18. 在vue项目引入天地图,根据经纬度获取具体地址
  19. 2973. 卡片游戏
  20. CH583电子价签在线管理方案

热门文章

  1. 申请百度文字识别APIkey和Secret Key+文字验证码识别案例
  2. 面试准备:逻辑智力题
  3. 2023北京影视技术设备展览会
  4. 思维导图(自我介绍)
  5. 【测试用例】文本框测试用例
  6. 基于SSD的CCTSDB交通标识数据集目标检测
  7. 视频号拍摄技巧和制作方法有哪些?
  8. 计算机长时间休眠后无法唤醒,为什么我电脑长时间不动进入待机状态却无法唤醒出现死机情况?必须强制关机!...
  9. 【智能车算法】电磁杆差比和差调参经验
  10. Excel导出(浏览器下载器下载导出Excel)