顶级程序员书单系列三:《深度学习入门-基于Python的原理与实现》

推荐理由

这本书用非常简单精妙的思想讲述了深度学习的基本原理。我感觉这本书告诉了我一个很重要的道理,如果你读了很多书都没有把一个概念读懂,那可能真的不一定是你的问题,还有可能是书的问题。一个好的老师,就应该把班里最笨的学生教会(如果他愿意学的话)。我想这本书,可以在我的顶级程序员书单系列排名第3-5位,非常值得一读。

我的部分笔记

深度学习经验
1.更深入地理解深度学习,最好的办法就是亲自实现。
2.光看数学公式和理论说明无法理解的情况下,可以尝试阅读源代码并运行。

Pyhon基本入门
import numpy as np
import matplotlib.pyplot as plt
if name == ‘main’:
print(“Hello world”)
print(1 + 2)
print(type(10))
a = [1, 2, 3, 4, 5]
print(a)
print(a[0:2])
me = {‘height’ : 180}
me[‘weight’] = 70
print(me[‘height’])
print(me)
print(True and False)
for i in [1, 2, 3]:
print(i)
def hello():
print(“I Love u”)
hello()

x = np.array([1.0, 2.0, 3.0])
y = np.array([2.0, 4.0, 6.0])
print(x + y)
print(x * y)

A = np.array([[1, 2], [3, 4]])
print(A)
print(A.shape)
# 数学上将一维数组称为向量,二维数组成为矩阵,三维数组称为张量
# 广播:形状不同的数组进行运算称为广播
B = np.array([10, 20])
print(A * B)
print(A[0])
print(A[1][0])

# 以0。1为单位,生成0到6的数据
x = np.arange(0, 6, 0.1)
y = np.sin(x)
plt.plot(x, y)
# plt.show()

感知机
感知机是什么:
感知机接收多个信号,输出一个信号
神经元计算输出信号总和,大于阈值(yu zhi)Θ时信号被激活
【x1】——w1——>
【y】
【x2】——w2——>

感知机原理:
w1 * x1 + w2 * x2 <= Θ ?y = 0 : y =1

感知机表示与门,非门,或门:
与门需要满足的条件
if name == ‘main’:
def AND(x1, x2):
w1, w2, theta = 0.5, 0.5, 0.7
tmp = x1 * w1 + x2 * w2
if tmp <= theta:
return 0
elif tmp > theta:
return 1

print(AND(0, 0))
print(AND(1, 0))

(x1 = 0, x2 = 0) => y = 0
(x1 = 1, x2 = 0) => y = 0
(x1 = 0, x2 = 1) => y = 1
(x1 = 1, x2 = 1) => y = 1

(w1 , w2, Θ) 取 (0.5, 0.5, 0.7)或(1.0, 1.0, 1.0)均可满足条件
类似的感知机也可以表示非门,或门

感知机的实现:
为了计算方便,我们把Θ换成-b(偏置),可以进行移项操作了
-b的作用是调整神经元被激活的容易程度
w1 * x1 + w2 * x2 <= Θ ?y = 0 : y =1 ->
w1 * x1 + w2 * x2 <= -b ?y = 0 : y =1 ->
b + w1 * x1 + w2 * x2 <= 0 ?y = 0 : y =1

异或门:
^
|1 0
|0 1
|————>
因为之前的模型(单层感知机)是线性的切割了,放在这里就不可以了
感知机的绝妙之处在于它可以“叠加层”

感知机实现异或门
def AND(x1, x2):
x = np.array([x1, x2])
w = np.array([0.5, 0.5])
b = -0.7
tmp = np.sum(w*x) + b
if tmp <= 0:
return 0
else:
return 1

def NAND(x1, x2):
x = np.array([x1, x2])
w = np.array([-0.5, -0.5])
b = 0.7
tmp = np.sum(w*x) + b
if tmp <= 0:
return 0
else:
return 1

def OR(x1, x2):
x = np.array([x1, x2])
w = np.array([0.5, 0.5])
b = -0.2
tmp = np.sum(w*x) + b
if tmp <= 0:
return 0
else:
return 1

def XOR(x1, x2):
s1 = NAND(x1, x2)
s2 = OR(x1, x2)
y = AND(s1, s2)
return y

print(XOR(0, 0))
print(XOR(0, 1))
print(XOR(1, 0))
print(XOR(1, 1))

与门或门是单层感知机,而异或门是2层感知机
XOR函数等价于:
【x1】———— 【s1】—
X y
【x2】———— 【s2】—

启示:单层感知机无法解决的东西,通过增加一层便可以解决

感知机总结
感知机是具有输入和输出的算法,在给定一个输入后,讲述出一个既定的值
感知机将权重和偏置设为既定参数
使用感知机可以表示与门和或门等逻辑电路
异或门无法通过单层感知机来表示
使用两层感知机表示异或门
单层感知机只能表示线性空间,多层感知机可以表示非线性空间
多层感知机在理论上可以表示计算机
即便对于复杂的函数,感知机也隐藏着能够表示它的可能性
坏消息是,设置权重的工作,现在还是人工进行的

神经网络
神经网络就是为了解决感知机只能手动调参的问题
神经网络的一个重要性质是它可以自动地从数据中学习到合适的权重参数
网络的名称:输入层,中间层,输出层的总数减去1
前文提到的感知机b + w1 * x1 + w2 * x2 <= 0 ?y = 0 : y =1
可以用函数来表示
y = { 0 ( b+w1x1+w2x2 <= 0 )
{ 1 ( b+w1x1+w2x2 > 0 )
我们可以通过引入新的式子y=h( b + w1x1 + w2x2)将上面的函数转换为
h(x) = { 0 ( x <= 0 )
{ 1 ( x > 0 )
引入激活函数的概念:将输入信号的总和转换为输出信号,将上面式子拆分如下
Y = h(a) 其中 a = b + w1x1 + w2x2
a表示输入信号的总和,h( ) 表示激活函数,y表示输出,h( ) 将输入信号a转化为了输出信号y

激活函数的重要地位:是连接感知机和神经网络的重要桥梁

神经网络各层信号传递
第一层:a1 = w11x1 + w12x2 + b1
第一层的图 == A = XW + B
第二层和第一层的激活函数不同
第一层使用sigmoid函数,第二层使用恒等函数
输出层的激活函数,根据问题的性质决定

一般地,回归问题可以使用恒等函数
二元问题可以使用sigmoid函数
多元问题可以使用softmax函数

3层神经网络的实现
import numpy as np
if name == ‘main’:
def init_network():
network = {}
network[‘W1’] = np.array([[0.1, 0.3, 0.5], [0.2, 0.4, 0.6]])
network[‘b1’] = np.array([[0.1, 0.2, 0.3]])
network[‘W2’] = np.array([[0.1, 0.4], [0.2, 0.5], [0.3, 0.6]])
network[‘b2’] = np.array([[0.1, 0.2]])
network[‘W3’] = np.array([[0.1, 0.3], [0.2, 0.4]])
network[‘b3’] = np.array([[0.1, 0.2]])
return network

def forward(network, x):
    W1, W2, W3 = network['W1'], network['W2'], network['W3']
    b1, b2, b3 = network['b1'], network['b2'], network['b3']

    a1 = np.dot(x, W1) + b1
    z1 = sigmoid(a1)
    a2 = np.dot(z1, W2) + b2
    z2 = sigmoid(a2)
    a3 = np.dot(z2, W3) + b3
    y = identity_function(a3)

    return y

def sigmoid(x):
    return 1 / (1 + np.exp(-x))

def identity_function(x):
    return x

network = init_network()
x = np.array([1.0, 0.5])
y = forward(network, x)
print(y)

softmax
import numpy as np
if name == ‘main’:
def softmax_old(a): # 存在溢出风险
exp_a = np.exp(a) # 指数函数
sum_exp_a = np.sum(exp_a)
y = exp_a / sum_exp_a
return y

def sofymax(a):
    c = np.max(a)
    exp_a = np.exp(a - c) # 溢出对策
    sum_exp_a = np.sum(exp_a)
    y = exp_a / sum_exp_a
    return y

a = np.array([0.3, 2.9, 4.0])
y = softmax_old(a)
print(y)
print(np.sum(y))

一般而言,使用softmax可以用概率的方法来处理问题,
实际上数组的大小关系没有发生特别大的变化
神经网络只把输出值最大的神经元作为结果进行识别
在神经网络分类时,输出层softmax可以省略
在实际问题中,由于指数函数需要计算,softmax也可以省略

手写数字识别
批处理:批处理对计算机的运行大有益处,可以大幅度缩短每张图像的处理时间
为什么批处理可以缩短处理时间?
因为大多数处理数值运算的库都进行了能高效处理大型数组运算的最优化
并且,在神经网络的运算中,当数据传送为瓶颈时,批处理可以减轻数据总线的负荷
(严格地讲,相对于数据读入,可以将更多的时间用在计算上)
也就是说,批处理一次性计算大型数组要比分开逐步计算各个小型数组更快

神经网络中的学习
数据—————人想到的算法—————答案
数据——人想到的特征量(SIFT,HOG)—机器学习(SVM,KNN)—答案
数据——神经网络(深度学习)—答案

损失函数
均方误差:均方误差会计算神经网络的输出和正确解监督数据的各个元素之差的平方

def mean_squared_error(y, t):
return 0.5 * np.sum((y - t) ** 2)
交叉熵误差:它的值是由正确标签所对应的输出结果决定的

def cross_entropy_error(y, t):
delta = 1e-7;
return -np.sum(t * np.log(y + delta))

Mini-batch:假设训练数据有6w个,从其中随机选择100个来训练
思想:用随机选择的小批量数据作为全体训练数据的近似值

猜你喜欢

转载自blog.csdn.net/qq_32648593/article/details/106772572