前言:
为什么从单层感知器开始补基础, 因为机器学习从没接触的人来说,不看这个 直接看卷曲神经会看不懂。 所以这篇补基础的文章,即是从单层感知器开始入手。
配置环境:
操作系统:windos7
语言: python3.5(建议使用 Anaconda3-4.2.0-Windows-x86_64)
所需数学基础: 高中数学, 知道什么是坐标, 知道怎么把 方程式转化为坐标曲线
1 简单必须的概念 (尽量用大白话概括)
1.1:tensorflow是什么?
是卷曲神经网络,一种机器学习的框架。
1.2: 机器学习是什么?
用代码去解决一些 现实中的问题。 比如 图像识别,字符识别,语音转文字 之类的。
1.3:怎么入门 ,好多东西看不懂, 数学不会?
卷曲神经的基础是机器学习,机器学习的入门是 单层感知器。 我们从单层感知器入手
数学用到哪看哪。 好多东西不会就从基础入手。 学着学着就会了。
1.4: 具体入门方式?:
好多教程,收费的,免费的 。 QQ群, 网易云课堂
2 什么是单层感知器:
首先我们要知道作为最基础的单层感知器是干什么的?
单层感知器是用来分类的。是机器学习的基础。 由多个单层感知器构成复杂的神经网络。
单层感知器功能 如下图: 对这个坐标系中的两个蓝点和一个黄点进行了一次 分类。 本文要讨论实现的问题就是如何实现下图的分类
3 解决问题 :
在一个坐标系中 点[3,3], [4,3] 是正值。点[1,1]是负值。 来构建一个神经网络,区分开这三个点。
首先补一下数学知识:
什么是矩阵: 矩阵是用长方阵列排列的 数字
矩阵加法和减法:加法减法类似 如下图
矩阵乘法: 数字乘矩阵
矩阵乘矩阵:
我们要解决的问题就是找到一根直线 使 正样本和负样本分开:
实现思路:
简单通俗的来说 : 就是把这个直线 作为一个方程。 例如 w0 + w1*x +w2y = 0
也就是把w0, w1 w2 不停的变换值 直到 找到一个合适的值,使正负样本分开。 就实现了我们的分类目的。 这里的w0 w1 w2 组合乘一个矩阵 [w0 ,w1 , w2]. 就是神经网络里面所所说的权重 权值。
如下就是代码实现。 先看我的注释 再抄两遍就会了
复制代码 跑一边 就会出现文章开始的图片了 。 python 自动生成的图片
以下是代码实现:
# coding:utf-8
import numpy as np
import matplotlib.pyplot as plt
X = np.array([
[1, 3, 3],
[1, 4, 3],
[1, 1, 1]
])
# 为什么样本坐标是 [3,3][4,3][1,1] 而这里多了个1 变成了
# [1, 3, 3],
# [1, 4, 3],
# [1, 1, 1]
# 因为 函数方程有一个常数项 比如 5 + x + 2y = 0 这里面的5 即是常数项。
# 如果矩阵没有第一位为1 则这个常数项无法体现
# 期望输出值
Y = np.array([1, 1, -1])
# 权重初始化 一行三列矩阵,取值范围 -1到1
W = (np.random.random(3)-0.5)*2
# 学习率
lr = 0.11
# 记录 循环点带次数
n = 0
# 输出值
O = 0
def update():
global X, Y, W, lr, n
n += 1
# 矩阵乘法 也即是 (3行3列)矩阵X 乘以 1列矩阵W.T
# (一行矩阵W, W.T 是将矩阵偏转成 1列)
# 其中 np.dat() 是矩阵相乘, 返回一个矩阵结果 在这里返回的是一个 3行1列
# np.sign() 返回数组中各元素的正负符号,用1和-1表示 数组元素分类
O = np.sign(np.dot(X, W.T))
''' 获取改变权值 这一块比较难懂。 因为我们的目的是在坐标上找到一根直线 来区分正样本和负样本 也即是 输入矩阵X X = np.array([ [1, 3, 3], [1, 4, 3], [1, 1, 1] ]) 用权重矩阵W和X的每行相乘。 这里W矩阵为 [w0,w1,w2] 例如X的第一行和W相乘 1*w0 + 3*w1 + 3*w2 最后 X*W.T会得到一个3行1列矩阵, 我们用np.sign() 返回数组中各元素的正负符号, 用1和-1表示 数组元素分类 最后会得到矩阵 O。 当矩阵O和期望输出 Y = np.array([1, 1, -1]) 相等时 我们的权重则计算完成 当我们获取到这个权重后, 我们就可以拿这个权重 去生成一个方程 w0 + x*w1 + y*w2=0 这个方程 输入我们的正样本 得出正值 输入负样本得出负值 这个方程 也即是 y = (-x*w1/w2) + (-w0/w2) 也即是 斜率为 -w1/w2 截距为 -w0/w2 '''
W_C = lr*(Y-O.T).dot(X)/int(X.shape[0])
W = W + W_C
for _ in range(100):
update()
O = np.sign(np.dot(X,W.T))
if (O == Y.T).all():# 如果实际输出等于期望输出 循环结束
break
# 正样本
x1 = [3, 4]
y1 = [3, 3]
# 负样本
x2 = [1]
y2 = [1]
# k是斜率 d是截距 获取方式 在权重那块写了
k = -W[1]/W[2]
d = -W[0]/W[2]
'''生成图片显示出效果'''
xdata = np.linspace(0, 5)
plt.figure()
plt.plot(xdata,xdata*k+d, 'r')
plt.plot(x1, y1, 'bo')
plt.plot(x2, y2, 'yo')
plt.show()
备注: 我学习的时候,比较疑惑权重改变公式的原理。 在此再次细讲下:
为什么权重改变公式为 W_C = lr*(Y-O.T).dot(X)/int(X.shape[0])
在此举一个简单的例子:
我们设: 样本 X[1,3,3]的期望输出为 1 。 在权重W为[w0, w1, w2]时。
X * W.T=[1*w0 + 3*w1 + 3*w2] 小于零。
也即是 期望输出值 O= np.sign(负数)=[-1]
所以: 期望输出-实际输出=Y-O=1-(-1)=2
这里我们将学习率 lr设定为1. 便于计算:
则我们的权重改变公式转化为了:
W_C = lr*(Y-O.T).dot(X)/int(X.shape[0]) ( 这里的这个函数 int(X.shape[0])是获取矩阵有多上行, 是为了算出改变的平均值)
= 1*([2].[1, 3, 3])/1
=[2, 6, 6]
新的权重为 W=W+W_C
首先: 在题目初期 W为原先值时 X*W.T < 0
现在我们把 新的权值 W=W+W_C 代入原先的公式:
X*(W+W_C).T = [1,3,3]*([w0,w1,w2] + [2, 6, 6]).T
= [1,3,3]*[w0+2, w1+6, w2+6].T
=1*(w0+2) + 3*(w1+6) + 3*(w2+6)
=w0 + 2 + 3w1 +18 + 3*w2 +18
= w0 +3w1 + 3w2 + (2+18+18)
=w0+ 3w1 + 3w2 +38
因为:原先的权重 是 X*W.T<0
也即是 w0+ 3w1 + 3w2 < 0
而权值更新后: X *(W+W_C).T 是
(w0+ 3w1 + 3w2) + 38
也即是 我们迭代一次, 这个值就增加38 . 直到加到结果为正值时。 迭代结束。 求得所 需要的权重
本文 参考地址: