说明: 就是巩固一下认识而已, 也是找了篇网上大佬的文章, 看了下写得还行, 抄一抄, 权当编程练习了, 目的成为了, 从代码的角度去认识这些, 莫名其妙的, 让人生畏的, 但其实简单的, 生物学名词 , 至于编码, 毕竟, 基本原理懂了, 剩下的其实就是去复制粘贴了呀.

我自己其实一直非常抵触 ML 的很多名词, 总结: 将简单概念复杂化, 这些老外搞的名词, 是真的恶心(当然也有可能是翻译过来哈哈) , 像什么, 监督学习, 机器学习, 人工智能, 学习率, 惩罚因子, 神经元, 神经网络, 卷积层, 池化, 全连接, 递归神经网络... 这尼玛, 光听上去就想放弃. 这写代码能跟生物扯上关系? 机器真能是智能呢, 还是智障? ..

真的是感觉, 是市场的推动, 搞这些莫名其妙的名词, 当我试着去, 以编程的视角来看时, 从数学视角来看时, 其实, 无非就是一些, 加权求和, 求平均, 多元函数求偏导, 最小二乘法, 参数估计, 高斯分布, 贝叶斯... 这些理论的综合应用而已.

我真的很不理解, 为什么那么多兄弟, 总喜欢把简单的东西复杂化, 故弄玄虚, 当然也许还是我太浅薄, 其实我自己很相信老子说的 为学日溢, 为道日损, 但我现在感觉, 有时候, 也需要 为学日损, 回归到最本真, 最基础的知识中来, 理论和实践要一起来整的.

抄一抄, 也见证一波, 从代码角度理解神经网络, 入门我感觉还是可以理解的.

神经元

其实就是一个计算过程, 输入一个向量, 然后每个分量有一个权值, 然后神经元的值就是, 输入向量 * 权值 再求和, 最后再加上一个偏置即可.

然后把这个加权求和的值, 传入一个 映射到 [0,1] 的实值的函数 (激活函数) , 这就是输出呀, 这个输出的过程, 也就前向传播 (feedforward). 当然, 叫前馈或者, 正反馈 可能会更准确一点.

case1

  • 输入: 一个向量 \(x = [2, 3]^T\)

  • 权重: 分量权重 \(w = [0, 1]^T​\)

  • 偏置: b=4 (作用是为了防止输出为0)

  • 函数: \(f(x) = 1 / (1+e^{-x})\)

则轻易算出:

该神经元的值为: \(w^Tx = (2*0 + 3*1) + 4 = 7\)

经激活函数后值: \(f(7) = 1/(1+e^{-7}) = 0.999\)

代码实现 - 神经元

import numpy as np

def sigmoid(x):
"""激活函数, 将输入实值x, 映射到[0-1]之间"""
return 1 / (1 + np.exp(-x)) class Neuron:
"""神经元及正反馈过程""" def __init__(self, weights, bias):
self.weights = weights
self.bias = bias def feedforward(self, inputs):
"""正反馈"""
node_value = self.weights.dot(inputs) + self.bias
return sigmoid(node_value) if __name__ == '__main__':
arr = np.array([2, 3])
weights = np.array([0, 1])
bias = 4 neuron = Neuron(weights, bias)
print(neuron.feedforward(arr)) # out
0.9990889488055994

神经网络

就是多个神经元之间有联系了, 还有一些其他的操作等.

图示:

输入还是一个向量, 假设是 \([x_1, x_2]^T\) 然后呢, 多了一个隐含层, 也是两个神经元 \((h_1, h2)\) 和一个输出值 \(o\), 其输入变成了 (h1, h2) . 这样, 就组成了一个网络.

case2

  • 输入: 一个向量 \(x = [2, 3]^T\)
  • 权重: 分量权重 \(w = [0, 1]^T\)
  • 偏置: b=0
  • 函数: \(f(x) = 1 / (1+e^{-x})\)

节点 h1, h2 对应的输入都是 \([x_1, x_2]^T\) 因此, h1, h2 的节点值是一样的

\(h_1 = h_2 = f(w^Tx + b)\)

\(=f(2*0 + 3*1)\)

$=f(3) $

\(= 0.952\)

继续往后

\(o_1 = f(w^T, [h1, h2]^T + b)\)

\(=f(0*h_1 + 1*h_2 + 0)\)

\(=f(0.952)\)

\(=0.722\)

此处加了一层后的网络, 输入 是 \([2, 3]^T\) 时, 输出是 0.722

当然, 一个神经网络的层数, 每层的神经元数都是可任意的. 学界已经证明了, 理论上, 一个3层(输入层, 隐含层, 输出层) 可以模拟出世界上几乎所有的函数, 只要节点数够多.

运作的前向逻辑都大致都是一样的: 输入在神经网络中向前传输, 最终得到输出. 而误差呢, 则通过实际值 与预测值 误差, 向后传播, 对应的调整则是, 每个神经元节点的输入权值线条呀.

一言蔽之神经网络: 正反馈 VS 负反馈

代码实现-正反馈

import numpy as np

def sigmoid(x):
"""激活函数, 将输入实值x, 映射到[0-1]之间"""
return 1 / (1 + np.exp(-x)) class Neuron:
"""神经元及正反馈过程"""
def __init__(self, weights, bias):
self.weights = weights
self.bias = bias def feedforward(self, inputs):
"""正反馈"""
node_value = self.weights.dot(inputs) + self.bias
return sigmoid(node_value) class Network:
"""神经网络"""
def __init__(self):
# 定义这两个本地变量, 没人能管到的那种
weights = np.array([0, 1])
bias = 0
self.h1 = Neuron(weights, bias)
self.h1 = Neuron(weights, bias)
self.o1 = Neuron(weights, bias) def feedforward(self, x):
"""正反馈"""
out_h1 = self.h1.feedforward(x)
out_h2 = self.h1.feedforward(x)
# 输出值
out_o1 = self.o1.feedforward(np.array([out_h1, out_h2]))
return out_o1 if __name__ == '__main__':
network = Network()
x = np.array([2, 3])
print(network.feedforward(x)) # out
0.7216325609518421

神经网络-训练

还是来案例吧. 假设有这样的一组原始数据

姓名 体重 身高 性别 (y)
youge 66 182 M
share 63 175 M
naive 45 166 F
beyes 98 185 F

稍微处理一下, 给数据做一个中心化, (易知 \(体重_{mean} = 68; \ 身高_{mean}=177\)) 然后 类别变量用 1 表示 M, 0 表示 F

姓名 体重 身高 性别 (y)
youge -2 5 1
share -5 -2 1
naive -23 -11 0
beyes 30 8 0

Loss

损失部分, 假设这里我们用 参数估计中的 均方误差 MSE 即误差平方的期望: \(E[ (参数值 - 真实值)^2]\)

\(MSE = \frac {1}{n} \sum\limits_{i=1}^n (y_i - \hat y_i)^2\)

n 表示样本数, 这里为 4

y 表示要预测的变量, 这里是 性别

训练的约束, 就是使得 MSE 的值尽可能小. -> 求解参数

MSE 的工作机制, 举个栗子, 假设网络的纵输出是 0, 也就是预测所有的 小伙伴都是 妹子.

姓名 \(y_i\) (真实值) \(\hat y_i\) (预测值) \((y_i - \hat y_i)\)
youge 1 0 1
share 1 0 1
naive 0 0 0
beyes 0 0 0

\(MSE = \frac {1}{4} (1 + 1 + 0 + 1) = 0.5\)

代码实现 - MSE



def mes_loss(y_true, y_predict):
"""
计算均方误差
:param y_true, arr 真实样本值组成的array
:param y_predict, arr 预测样本值组成的array
:return: float, 总损失
"""
return ((y_true - y_predict) ** 2).mean() if __name__ == '__main__':
y = np.array([1, 1, 0, 0])
y_hat = np.array([0, 0, 0, 0]) print("MSE: ", mes_loss(y, y_hat)) # out
MSE: 0.5

好了, 上篇就搬砖到这里吧, 目的是, 如何直观来理解神经网络, 从代码的角度来理解, 真的可能秒懂, 而看图和概念, 反而老是会想到什么 生物学的概念, 莫名其妙.

然后就是, 反复又反复地 认识 ML 的核心问题, 如何定义模型, 如何衡量损失, 如何优化损失以求解最优模型参数 , 还是蛮好理解的, 其实. 下篇搬砖, 就接着, 后面的 损失优化和参数估计来展开呀.

代码视角-神经网络-Python 实现(上)的更多相关文章

  1. 深度学习与CV教程(6) | 神经网络训练技巧 (上)

    作者:韩信子@ShowMeAI 教程地址:http://www.showmeai.tech/tutorials/37 本文地址:http://www.showmeai.tech/article-det ...

  2. 使用2to3将代码移植到Python 3-转

    http://m.blog.csdn.net/blog/merryken/9104199# ❝ Life is pleasant. Death is peaceful. It’s the transi ...

  3. 在VS代码中编辑Python

    在VS代码中编辑Python Python扩展提供了许多用于在Visual Studio代码中编辑Python源代码的功能: 自动完成和智能感知 在终端中运行选择/行(REPL) 格式化 重构 也见L ...

  4. 神经网络前向后向传播(理论推导+代码) 单层神经网络相当于logistic regression

    建立神经网络的主要步骤是: 1. 定义模型结构(例如输入特征的数量) 2. 初始化模型的参数 3. 循环: # 3.1 计算当前损失(正向传播) # 3.2 计算当前梯度(反向传播) # 3.3 更新 ...

  5. python 图片上传写入磁盘功能

    本文是采取django框架,前端上传图片后端接收后写入磁盘,数据库记录图片在磁盘上的路径(相对),以下是前端上传到后端入库的基本流程 一. html代码 <!DOCTYPE html> & ...

  6. 植物大战僵尸的代码如何使用python来实现

    前言 文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者:程序IT圈 PS:如有需要Python学习资料的小伙伴可以加点击下方链 ...

  7. Python入门(上)

    Python入门(上) Python入门(上) 简介 Python 基础语法 行与缩进 注释 运算符 标准数据类型 变量 编程流程 顺序(略) 分支 if 循环 for while break 和 c ...

  8. 一键自动发布ipa(更新svn,拷贝资源,压缩资源,加密图片资源,加密数据文件,加密lua脚本,编译代码,ipa签名,上传ftp)

    一键自动发布ipa(更新svn,拷贝资源,压缩资源,加密图片资源,加密数据文件,加密lua脚本,编译代码,ipa签名,上传ftp) 程序员的生活要一切自动化,更要幸福^_^. 转载请注明出处http: ...

  9. 《编写高质量代码:改善Python程序的91个建议》读后感

    编写高质量代码:改善Python程序的91个建议  http://book.douban.com/subject/25910544/ 1.(建议16)is 用于判断两个对象的id是否相等,==才是判断 ...

  10. 在 C 代码中嵌入 Python 语句或使用 Python 模块 (Visual Studio 2013 环境设置)

    1) 新建一个 内嵌 Python 语句的 C 代码, // This is a test for check insert the Python statements or module in C. ...

随机推荐

  1. 【计算机】常见CPU指令集发展及其关系

    [计算机]常见 CPU 指令集发展及其关系 CPU 与指令集 任何计算机都有一块 CPU,CPU 有其支持的指令集,根据指令集间的兼容性,一种 CPU 可能同时支持多种指令集. 指令集中记录了 CPU ...

  2. Linux - 内核版本升级

    测试时间:2024年5月15日,本文测试CentOS7.9的内核版本升级 测试结论:不要选择手动编译的方式!!! 一.使用第三方仓库(ELRepo) (1)升级前内核查看(3.10.0-1160.el ...

  3. C++ open()和read()函数使用详解

    对于Framework工程师来说,必要C或者C++编程能力是必须的,像对设备节点的操作是最基本的操作,那么我们便会用到open和read函数.open()函数用于打开文件,而read()函数用于从打开 ...

  4. Web前端入门第2问:前端开发是什么?与后端、全栈的区别是什么?一个完整的Web项目有哪些角色参与?

    一个完整的Web项目有哪些角色参与? 提出需求(这一步可以是甲方,也可以是用户) 需求分析,画出原型图(产品经理) 根据原型图输出 UI 界面及交互图(UI/UX设计师) 根据UI及交互效果画出页面, ...

  5. DBeaver连接mysql时,报错Public Key Retrieval is not allowed

    解决 在新建连接的时候,驱动属性里设置 allowPublicKeyRetrieval 的值为 true.

  6. Django项目如何配置日志文件信息

    1.以dict的方式配置在settings.py中 # 日志文件简单配置 ''' LOGGING = { "version": 1, "disable_existing_ ...

  7. CentOS——磁盘分区

    Centos7-磁盘分区磁盘层次结构–磁盘分区方法情况一:磁盘分区–磁盘小于2T fdisk情况二:磁盘分区–磁盘大于2T centos6:parted centos7:fdisk一.磁盘小于2T情况 ...

  8. Linux上安装配置InstantClient及64位系统Pl/SQL配置

    1.首先到官网下载文件:http://www.oracle.com/technetwork/database/features/instant-client/index-097480.html?ssS ...

  9. mvc api 下载文件问题

    背景:前后端分离项目,文件下载 项目中 因为实际文件名和路径里的文件名 不一致(一般路径文件名需要使用唯一名字) 刚开始使用返回链接的方式,会出现图片直接预览,文件名会以路径文件名下载,用户体验不好. ...

  10. 【JVM之内存与垃圾回收篇】本地方法栈

    本地方法栈 Java 虚拟机栈于管理 Java 方法的调用,而本地方法栈用于管理本地方法的调用. 本地方法栈,也是线程私有的. 允许被实现成固定或者是可动态扩展的内存大小.(在内存溢出方面是相同的) ...