一、什么是深度学习?
在人工智能领域,有一个方法叫机器学习。在机器学习方法中有一类算法叫神经网络:
如下图:
(神经元)
(神经元之间的连接)
Layer L1 : 输入层 Layer L2: 隐藏层
Layer L3: 输出层
图(一)中的每个圆圈都是一个神经元, 连接每个神经元之间的连线是神经元之间的连接。上面的神经元被分成了3层,层与层之间的神经元有连接, 而同一层之间的神经元是没有连接。最左边的(Layer L1)为输入层, 负责接收输入数据;中间的层也就(Layer L2)为隐藏层;最右边的的层(Layer L3)为输出层,可以从该层获取神经网络的输出数据。
输入层与输出层之间的都是隐藏层,层数(大于2)的神经网络叫深度神经网络。而深度学习,就是使用深层架构(深度神经网络)的机器学习方法。
深层网络与浅层网络之间的联系:
深层网络在表达上要直观明了一些。只有一个隐藏层的神经网络也能拟合函数,但是在这一个隐藏层中就需要很多的神经元才能将所要表达的展示出来。而深层网络可以用很少的神经元(相对单隐层)就可以拟合同样的函数。所以在拟合函数的时候,就有单隐层(浅而宽),多隐层(深而窄)俩种方法来拟合了。但相对来说深层网络更节省资源,并且不容易训练,对于深层网络需要大量的数据,以及很多技巧才能训练出来一个较好的深层网络。
二、感知器(神经元)
感知器——神经网络的组成单元(神经元)
感知器定义:
公式打不了,所以直接截图了,很尴尬了,)
例子:用感知器实现and函数
设计一个感知器,让它实现and运算。and是一个二元函数(带有两个参数X1和X2),真值表如下:
X1 | X2 | y |
---|---|---|
0 | 0 | 0 |
0 | 1 | 0 |
1 | 0 | 0 |
1 | 1 | 1 |
0 表示false, 1表示true。
令W1 = 0.5; W2=0.5;b = -0.8, 而激活函数 f 就是前面写出来的阶跃函数,此时的感知器就相当于and函数。
将上面的真值表代入公式(一),计算得出输出,可以验证第一行:
y = f(w*X + b)
= f(W1X1 + W2X2 + b)
= f(0.5*0+0.5*0-0.8)
=f(-0.8) =0
即当X1,X2都为0时,y为0。
例子:用感知器实现or函数
设计一个感知器,让它实现or运算。or是一个二元函数(带有两个参数X1和X2),真值表如下:
X1 | X2 | y |
---|---|---|
0 | 0 | 0 |
0 | 1 | 1 |
1 | 0 | 1 |
1 | 1 | 1 |
0 表示false, 1表示true。
令W1 = 0.5; W2=0.5;b = -0.3 可以验证第二行:
y = f(w*X + b)
= f(W1X1 + W2X2 + b)
= f(0.5*0+0.5*1-0.8)
=f(0.2) =1
即当X1=0, X2=1时,y为1。
三、感知器的其他应用
感知器不仅仅可以实现简单的不二运算,它还可以拟合线性函数,任何的线性分类或线性回归问题都可以用感知器来解决。前面的布尔运算可以看作是二分类问题, 即给定一个输入,输出0(属于0这个类别)或输出1(属于1这个类别)。如下面所示,and
运算是一个线性分类问题,即可以用一条直线把分类0(false,红叉表示)和分类1(true,绿点表示)分开。但是不可以进行异或运算。
四、感知器的训练
获得权重项和偏置项:
利用感知器训练算法:将权重项和偏置项初始化为0, 然后利用感知器规则迭代更新wi和b, 直到训练完成。
其中
wi是输入xi对应的权重项,b是偏置项(可以把b看作是值永远为1的输入xb所对应的权重),t是样本的实际值,一般为label, 而y是感知器的输出值,他是有公式1计算出来的。yita是学习率,控制每一步权重的更新幅度(或者说是步长)。
每次从训练数据中取出一个样本的输入向量X, 使用感知器计算其输出y, 在根据感知器规则来进行多次的迭代更新,得到最终的权重。
最后上代码:
感知器类:
# -*- coding: utf-8 -*-
# !/usr/bin/env python
# @Time : 2019/4/25 15:57
# @Author : xhh
# @Desc : 机器学习入门--感知器(cell)
# @File : test_perceptorn.py
# @Software: PyCharm
from __future__ import print_function
from functools import reduce
class VectorOp(object):
"""
实现向量计算操作
"""
@staticmethod
def dot(x, y):
"""
计算两个向量的内积
1、首先把x[x1, x2, x3...] 和y[y1, y2, y3...]按元素相乘
2、变成[x1*y1, x2*y2,x3*y3]
3、然后利用reduce求和
:param y:
:return:
"""
return reduce(lambda a, b: a + b,VectorOp.element_multiply(x, y), 0.0)
@staticmethod
def element_multiply(x, y):
"""
将两个向量x和y按元素相乘
1、首先把x[x1, x2, x3...]和y[y1, y2, y3...]打包在一起
2、变成[(x1,y1),(x2, y2),(x3,y3),...]
3、然后利用map 函数计算[x1*y1, x2*y2, x3*y3]
:param y:
:return: 返回列表集合
"""
return list(map(lambda x_y: x_y[0] * x_y[1], zip(x, y)))
@staticmethod
def element_add(x, y):
"""
将两个向量x和y按元素相加
1、首先把x[x1, x2, x3...]和y[y1, y2, y3...]打包在一起
2、变成[(x1,y1),(x2, y2),(x3,y3),...]
3、然后利用map 函数计算[x1+y1, x2+y2, x3+y3]
:param y:
:return: 返回一个列表
"""
return list(map(lambda x_y: x_y[0] + x_y[1], zip(x, y)))
@staticmethod
def scala_multiply(v, s):
"""
将向量v中的每个元素和标量s相乘
:param s: 标量s
:return: 返回map
"""
return map(lambda e: e * s, v)
class Perceptron(object):
def __init__(self, input_num, activator):
"""
初始化感知器,设置输入参数的个数,以及激活函数。
激活函数的类型为double —> double
:param input_num:
:param activator:
"""
self.activator = activator
# 设置权重向量初始化为0
self.weights = [0.0]*input_num
# 偏置项初始化为0
self.bias = 0.0
def __str__(self):
"""
打印学习到的权重、偏置项
:return:
"""
return 'weight\t:%s\nbias\t:%f\n'%(self.weights, self.bias)
def predict(self, input_vec):
"""
输入向量,输出感知器的计算结果
1、计算输入的向量input_vec[x1, x2, x3...]和权重weights[w1, w2, w3,...]的内积
2、然后加上bias
:param input_vec:
:return:
"""
return self.activator(
VectorOp.dot(input_vec, self.weights)+self.bias)
def train(self, input_vecs, labels, iteration, rate):
"""
输入训练数据:一组向量、以及每个向量对应的label;以及训练数和学习率
:param input_vecs: 输入的向量
:param labels: 每个向量的标签
:param iteration: 迭代次数
:param rate: 学习率
:return:
"""
for i in range(iteration):
self._one_iteration(input_vecs, labels, rate)
def _one_iteration(self, input_vecs, labels, rate):
"""
每迭代一次,把所有的训练数据过一遍
1、把输入和输出打包在一起,生成样本列表[(input, label),...]
2、而每个训练样本(samples)都是(input_vec, label)
:param input_vecs: 输入向量
:param labels: 向量对应的标签
:param rate: 学习率
:return:
"""
samples = zip(input_vecs, labels)
# 对每个样本,感知感知器的规则更新权重
for (input_vec,label) in samples:
# 计算感知器在当前权重下的输出
output = self.predict(input_vec)
# 更新权重
self._update_weights(input_vec, output, label, rate)
def _update_weights(self, input_vec, output, label, rate):
"""
按照感知器规则更新权重
1、首先计算本次更新的delta
2、然后把input_vec[x1, x2, x3,...]向量中的每个值乘上delta
3、最后再把权重更新按元素加到原先的weights[w1, w2, w3,...]上
:param output: 输入向量
:param label: 输出向量
:param rate: 学习率
:return:
"""
delta = label - output
self.weights = VectorOp.element_add(
self.weights, VectorOp.scala_multiply(input_vec, rate * delta))
# 更新bias
self.bias += rate * delta
and函数的实现:
def f(x):
"""
定义激活函数
:param x:
:return:
"""
return 1 if x > 0 else 0
def get_training_dataset():
"""
基于and真值表构建训练数据
:return:
"""
# 构建训练数据, 输入向量的列表
input_vecs = [[1, 1],[0, 0], [1, 0], [0, 1]]
# 期望的输出列表
# [1, 1]—> 1, [0, 0] —>0, [1, 0] —>0, [0, 1] —>0
labels = [1, 0, 0, 0]
return input_vecs, labels
def train_and_perceptron():
"""
使用and真值表训练感知器
:return:
"""
# 创建感知器,输入参数个数为2(and是一个二元函数),激活函数为f
p = Perceptron(2, f)
# 训练,迭代10轮, 学习速率为0.1
input_vecs, labels =get_training_dataset()
p.train(input_vecs, labels, 10, 0.1)
# 返回训练好的感知器
return p
测试写好的感知器:
if __name__ == '__main__':
# 训练感知器
and_perception = train_and_perceptron()
# 打印训练获得权重
print(and_perception)
# 测试
print('1 and 1 = %d' % and_perception.predict([1, 1]))
print('0 and 0 = %d' % and_perception.predict([0, 0]))
print('1 and 0 = %d' % and_perception.predict([1, 0]))
print('0 and 1 = %d' % and_perception.predict([0, 1]))
运行结果:
到此,感知器就写完了,是参考别的来理解,学习的,把自己的学习过程记下来~~~~
大家可以关注我和我小伙伴的公众号~~~这里有我和我的小伙伴不定时的更新一些python技术资料哦!!大家也可以留言,讨论一下技术问题,希望大家多多支持,关注一下啦,谢谢大家啦~~
本文分享自 Python爬虫scrapy 微信公众号,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文参与 腾讯云自媒体同步曝光计划 ,欢迎热爱写作的你一起参与!