模拟退火算法
目的:
- 为具有NP复杂性的问题提供有效的近似求解算法
- 克服优化过程陷入局部极小
- 克服初值依赖性
模拟退火的过程:
- 加温过程。增强粒子的热运动,使其偏离平衡位置。
- 等温过程。对于与周围环境交换热量而温度不变的封闭系统,系统状态的自发变化总是朝着自由能减少的方向进行,当自由能达到最小时,系统达到平衡态。
- 冷却过程。使粒子的热运动减弱并渐趋于有序,系统能量下降,从而得到低能的晶体结构。
模拟退火的思想
基于Monte迭代求解策略的一种随机寻优算法,出发点是基于物理退火过程与组合优化之间的相似性,SA由某一较高温度开始,利用具有概率突跳特性的Montropolis抽样策略在解空间中进行随机搜索,伴随温度的不断下降重复抽样过程,最终得到问题的全局最优解。
模拟退火的步骤
- 给定初始温度t= t 0 t_0 t0,随机产生初始状态s= s 0 s_0 s0,令k=0
- Repeat:
- Repeat:
- 产生新的状态 s j s_j sj=Genete(s);
- if min{1, e − C ( s j ) − C ( s ) / t k e^{-C(s_j)-C(s)/t_k} e−C(sj)−C(s)/tk}>=random[0,1] s= s j s_j sj;
- Until 抽样稳定准则满足
- 退温 t k + 1 = u p d a t e ( t k ) t_{k+1}=update(t_k) tk+1=update(tk)并令k=k+1
- Until算法终止准则满足
- 输出算法搜索结果
- Repeat:
标准模拟退火算法流程图
从算法结构中知,新状态产生函数,新状态接受函数,退温函数,抽样稳定准则和退火结束准则以及初始温度是直接影响算法优化的结果的主要环节。
模拟退火冷却进度表:
冷却进度表是指从某一高温状态T向低温状态冷却时的降温函数,设时刻的温度为T(t),则经典的模拟退火算法的降温方式为:
T
(
t
)
=
T
0
lg
(
1
+
t
)
T(t)= \frac{T_0}{\lg(1+t)}
T(t)=lg(1+t)T0
快速模拟退火算法的降温方式为:
T
(
t
)
=
T
0
1
+
t
T(t)=\frac{T_0}{1+t}
T(t)=1+tT0
初始温度:
对于模拟退火算法来说,初始温度越高,获得高质量解的几率就越大,但是花费的时间也会随之增加,因此,初始温度的确定应该同时考虑计算效率与优化常量。常用的方法:
-
均匀抽样一组状态,以及各状态的目标值的方差为初温
-
随机产生一组状态,确定状态间的最大目标值,然后根据差值,利用一定的函数确定初始温度:(其中pr为初始接受概率)
T 0 = Δ m a x P r T_0=\frac{\Delta max}{Pr} T0=PrΔmax
内循环终止原则
- 检验目标函数的均值是否稳定
- 连续若干步的目标值变化比较小
- 按一定的步数进行抽样
外循环终止原则
- 设置终止温度
- 设置外循环迭代次数
- 算法搜索到的最优值连续保持若干步保持不变
- 检验系统熵是否稳定
模拟退火算法的优点
实验性能高,初值鲁棒性强,通用容易实现
模拟退火算法的缺点
要求较高的初始温度,较慢的降温速率,较低的终止温度以及各温度下足够多此的抽样因而模拟退火算法大部分情况下优化过程较长。
模拟退火算法的实例:
问题:一旅行小伙想去国内34个城市旅游,要求一次走完不重复且走的总距离最短,有已知的34个城市的经纬度,求最短总距离。
代码实现
import csv
import math
import numpy as np
import random
from matplotlib import pyplot as plt
#导入数据
filename='旅行商数据/旅行商数据.csv'
with open(filename) as f:
reader=csv.reader(f)
header_row=next(reader)
x=[]
y=[]
longtitudes=[]
dimensionalitys=[]
for row in reader:
x.append(row[1])
y.append(row[2])
longtitudes=[float(x) for x in x]
dimensionalitys=[float(y) for y in y]
longtitudes.append(longtitudes[0])
dimensionalitys.append(dimensionalitys[0])
#构建距离矩阵
d=[]
rows=31
columns=31
pi=3.1415926
for row in range(rows):
d.append([])
for column in range(columns):
x1=longtitudes[row]*pi/180
y1=dimensionalitys[row]*pi/180
x2=longtitudes[column]*pi/180
y2=dimensionalitys[column]*pi/180
num = 6370 * math.acos((math.cos(x1 - x2) * math.cos(y1) * math.cos(y2) + math.sin(y1) * math.sin(y2)))
d[row].append(num)
#产生较好的初始路径并计算初始长度
path=[0]
path1=np.random.permutation(29)+1
path.extend(path1)
path.append(30)
temp=0
for i in range(30):
temp=temp+d[path[i]][path[i+1]]
long=temp
#设置初始值
t=0.1**30
T=1
at=0.999
L=10*300
a=[]
#模拟退火过程
while t<T:
for i in range(L):
a=random.sample(range(2,29),2)
a.sort()
a1=a[0]
a2=a[1]
r=np.random.uniform(0,1)
df = d[path[a1 - 2]][path[a2 - 1]] + d[path[a1 - 1]][path[a2]] - d[path[a1 - 2]][path[a1 - 1]] - \
d[path[a2 - 1]][path[a2]]
if df < 0:
long = long + df
change_path = path[a2 - 1:a1 - 2:-1]
path[a1 - 1:a2] = change_path
elif math.exp(-df / T) > r:
long = long + df
change_path = path[a2 - 1:a1 - 2:-1]
path[a1 - 1:a2] = change_path
T = T * at
print(long)
print(path)
#"画路线图"
plt.rcParams['font.sans-serif'] = ['SimHei']
xx = []
yy = []
for i in range(31):
aa = path[i]
aa1 = longtitudes[aa]
aa2 = dimensionalitys[aa]
if aa > 0 & aa < 30:
plt.text(aa1, aa2, aa)
elif aa == 0:
plt.text(aa1, aa2, "中心城市")
xx.append(aa1)
yy.append(aa2)
plt.plot(xx, yy)
plt.show()
运行效果:
浅层神经网络(Shallow neural networks)
图1
公式1
公式2
图2
如图1所示为上周所学由图1和公式1建立联系,需要输入特征向量 x i x_{i} xi,参数 ω \omega ω和b,就可以通过公式1计算出z,再通过公式2用z通过函数 a = σ ( z ) a=\sigma(z) a=σ(z)就可以计算出loss function L( α \alpha α,y)。
神经网络就如图2所示,可以把n个sigmoid单元堆叠起来形成一个神经网络。因而,对于图1中的节点的计算就是:第一步,计算 z = w T ∗ x i + b z=w^{T}*x_i+b z=wT∗xi+b。第二步,通过 α = σ ( z ) \alpha=\sigma(z) α=σ(z)计算 a a a。类似的,在图2中对应的三个节点,第一步先计算第一层网络中的各个节点的相关数 z [ 1 ] z^{[1]} z[1],然后计算 a [ 1 ] a^{[1]} a[1]。计算下一层的神经网络也是同样的原理。
符号表示:
[ m ] ^{[m]} [m]表示m层神经网络中相关节点的数,这些节点的集合被称为第m层神经网络。
正向计算过程如公式3所示:
公式3
在计算下一层神经网络节点的时候需要上一层的输出,则,需要使用另外一个线性方程如公式4,公式5所示,对应的参数计算 z [ 2 ] z^{[2]} z[2],计算 a [ 2 ] a^{[2]} a[2],此时 a [ 2 ] a^{[2]} a[2]就是最终神经网络的输出,用 y ^ \hat{y} y^表示网络的输出。
公式4
公式5
计算神经网络的输出
如图3所示为两层神经网络的结构:
图3
其中,x表示输入特征, a a a表示每个神经元的输出,W表示特征的权重,上标表示神经网络的层数(隐藏层为1),下标表示该层的第几个神经元。
神经网络的计算
如图四所示,用圆圈表示神经网络的计算单元,逻辑回归的计算有两个步骤,首先计算出z,然后第二步以sigmoid函数为激活函数计算z(得出 a a a),一个神经网络就是这样的步骤重复多次运算。
图4
那么,如果是两层神经网络,就从隐藏层的第一个神经元开始计算,就如图4,一个单独的神经元的计算类似。这样神经元的计算与逻辑回归一样分为两步,小圆圈代表了计算的两个步骤。
- 第一步:计算 z 1 [ 1 ] z_1^{[1]} z1[1], z 1 [ 1 ] = w 1 [ 1 ] T x + b 1 [ 1 ] z_1^{[1]}=w_1^{[1]T}x+b_1^{[1]} z1[1]=w1[1]Tx+b1[1]。
- 第二步:通过激活函数计算 a 1 [ 1 ] a_1^{[1]} a1[1], a 1 [ 1 ] = σ ( z 1 [ 1 ] ) a_1^{[1]}=\sigma(z_1^{[1]}) a1[1]=σ(z1[1])。
隐藏层的第二个以及后面的两个神经元的计算过程一样,只是注意符号不同,最终分别得到
a
2
[
1
]
a_2^{[1]}
a2[1],
a
3
[
1
]
a_3^{[1]}
a3[1],
a
4
[
1
]
a_4^{[1]}
a4[1],则计算方式为:
z
1
[
1
]
=
w
1
[
1
]
T
∗
x
+
b
1
[
1
]
,
a
1
[
1
]
=
σ
(
z
1
[
1
]
)
z_1^{[1]}=w_1^{[1]T}*x+b_1^{[1]},a_1^{[1]}=\sigma(z_1^{[1]})
z1[1]=w1[1]T∗x+b1[1],a1[1]=σ(z1[1])
z 2 [ 1 ] = w 2 [ 1 ] T ∗ x + b 2 [ 1 ] , a 2 [ 1 ] = σ ( z 2 [ 1 ] ) z_2^{[1]}=w_2^{[1]T}*x+b_2^{[1]},a_2^{[1]}=\sigma(z_2^{[1]}) z2[1]=w2[1]T∗x+b2[1],a2[1]=σ(z2[1])
z 3 [ 1 ] = w 3 [ 1 ] T ∗ x + b 3 [ 1 ] , a 3 [ 1 ] = σ ( z 3 [ 1 ] ) z_3^{[1]}=w_3^{[1]T}*x+b_3^{[1]},a_3^{[1]}=\sigma(z_3^{[1]}) z3[1]=w3[1]T∗x+b3[1],a3[1]=σ(z3[1])
z 4 [ 1 ] = w 4 [ 1 ] T ∗ x + b 4 [ 1 ] , a 4 [ 1 ] = σ ( z 4 [ 1 ] ) z_4^{[1]}=w_4^{[1]T}*x+b_4^{[1]},a_4^{[1]}=\sigma(z_4^{[1]}) z4[1]=w4[1]T∗x+b4[1],a4[1]=σ(z4[1])
向量化的计算
由于神经网络有2个甚至多个隐藏层,因此用for循环做起来很低效。所以需要将以上四个等式向量化,向量化过程是将神经网络中的一层神经元参数纵向堆积起来。例如将隐藏层中的w纵向堆积起来就变成了一个(4,3)的矩阵,用符号 W [ 1 ] W^{[1]} W[1]表示。也因此公式8, z [ n ] = w [ n ] + b [ n ] z^{[n]}=w^{[n]}+b^{[n]} z[n]=w[n]+b[n],公式9 a [ n ] = σ ( z [ n ] ) a^{[n]}=\sigma(z^{[n]}) a[n]=σ(z[n])。
详细过程如公式6和公式7所示:
公式6
公式7
对于神经网络的第一层,给与一个输入x,得到 a [ 1 ] a^{[1]} a[1],x可以表示为 a [ 0 ] a^{[0]} a[0],通过相似的衍生,则后一层的表示同样可以写成类似的形式,得到 a [ 2 ] a^{[2]} a[2], y ^ = a [ 2 ] \hat{y}=a^{[2]} y^=a[2],则详细过程如公式8和公式9所示。
多样本向量化
图5
逻辑回归是将各个训练样本组合成矩阵,对矩阵的各列进行计算。神经网络是通过对逻辑回归中的等式简单变形,让神经网络计算输出值。具体步骤为:用第一个训练样本 x [ 1 ] x^{[1]} x[1],计算出预测值 y ^ [ 1 ] \hat{y}^{[1]} y^[1],得到第一个训练样本的结果。用训练样本 x [ 2 ] x^{[2]} x[2],计算出预测值 y ^ [ 2 ] \hat{y}^{[2]} y^[2],直至用 x [ m ] x^{[m]} x[m]计算出 y ^ [ m ] \hat{y}^{[m]} y^[m]。
如果有一个非向量化形式的出现,而且要计算出它的预测值,对于所有的训练样本,需要让
i
i
i从1到m实现这四个等式:
z
[
1
]
(
i
)
=
W
[
1
]
(
i
)
+
b
[
1
]
(
i
)
z^{[1](i)}=W^{[1](i)}+b^{[1](i)}
z[1](i)=W[1](i)+b[1](i)
a [ 1 ] ( i ) = σ ( z [ 1 ] ( i ) ) a^{[1](i)}=\sigma(z^{[1](i)}) a[1](i)=σ(z[1](i))
z [ 2 ] ( i ) = W [ 2 ] ( i ) a [ 1 ( i ) ] + b [ 2 ] ( i ) z^{[2](i)}=W^{[2](i)}a^{[1(i)]}+b^{[2](i)} z[2](i)=W[2](i)a[1(i)]+b[2](i)
a [ 2 ] ( i ) = σ ( z [ 2 ] ( i ) ) a^{[2](i)}=\sigma(z^{[2](i)}) a[2](i)=σ(z[2](i))
【注】 a [ 2 ] ( i ) a^{[2](i)} a[2](i)是指第𝑖个训练样本而[2]是指第二层。
对于上面的这个公式中的 ( i ) ^{(i)} (i),是所有依赖于训练样本的变量,即将 ( i ) (i) (i)添加到 x x x,z, a a a。则向量化为:
公式10:
公式11:
公式12
公式13
定以矩阵 X X X等于训练样本,将它们组合成矩阵的各列,形成一个n维或n乘以m维矩阵,之后待入公式13中计算。
激活函数
图6
适用范围:
sigmoid激活函数:除了输出层是一个二分类问题外基本不会用它
tanh激活函数:适用于所有场合
ReLu激活函数:最常用的默认激活函数,若不确定用哪个激活函数,就选择ReLu或者leaky ReLu。
神经网络的梯度下降:
单隐层神经网络会有 W [ 1 ] W^{[1]} W[1], b [ 1 ] b^{[1]} b[1], W [ 2 ] W^{[2]} W[2], b [ 2 ] b^{[2]} b[2]这些参数,还有个 n x n_x nx表示输入特征的个 数, n [ 1 ] n^{[1]} n[1]表示隐藏单元个数, n [ 2 ] n^{[2]} n[2]表示输出单元个数。那么参数: 矩阵 W [ 1 ] W^{[1]} W[1]的维度就是( n [ 1 ] n^{[1]} n[1], n [ 0 ] n^{[0]} n[0] ), b [ 1 ] b^{[1]} b[1]就是 n [ 1 ] n^{[1]} n[1]维向量,可以写成( n [ 1 ] n^{[1]} n[1] , 1),就是一个的列向量。 矩阵 W [ 2 ] W^{[2]} W[2]的维度就是( n [ 2 ] n^{[2]} n[2] , n [ 1 ] n^{[1]} n[1] ), b [ 2 ] b^{[2]} b[2]的维度就是( n [ 2 ] n^{[2]} n[2], 1)维度。神经网络的成本函数,假设在做二分类任务,那么你的成本函数等于:
Cost function :
J
(
W
[
1
]
,
b
[
1
]
,
W
[
2
]
,
b
[
2
]
)
=
1
m
∑
i
=
1
n
L
(
y
^
,
y
)
J(W^{[1]},b^{[1]},W^{[2]},b^{[2]})=\frac{1}{m}\sum_{i=1}^{n}L(\hat{y},y)
J(W[1],b[1],W[2],b[2])=m1i=1∑nL(y^,y)
loss function 和之前logistic回归一样
训练参数需要做梯度下降,在训练神经网络的时候,随机初始化参数很重要,而不是初始化全为0。当参数初始化某些值后,每次梯度下降都会循环计算以下预测值:
y
^
,
(
i
=
1
,
2
,
.
.
.
,
m
)
\hat{y},(i=1,2,...,m)
y^,(i=1,2,...,m)
d W [ 1 ] = d J d w [ 1 ] , d b [ 1 ] = d J d b [ 1 ] dW^{[1]}=\frac{dJ}{dw^{[1]}},db^{[1]}=\frac{dJ}{db^{[1]}} dW[1]=dw[1]dJ,db[1]=db[1]dJ
d W [ 2 ] = d J d W [ 2 ] , d b [ 2 ] = d J d W [ 2 ] dW^{[2]}=\frac{dJ}{dW^{[2]}},db^{[2]}=\frac{dJ}{dW^{[2]}} dW[2]=dW[2]dJ,db[2]=dW[2]dJ
其中:
W
[
1
]
:
=
W
[
1
]
−
a
d
W
[
1
]
,
b
[
1
]
:
=
b
[
1
]
−
a
d
b
[
1
]
W^{[1]}:=W^{[1]}-a dW^{[1]},b^{[1]}:=b^{[1]}-a db^{[1]}
W[1]:=W[1]−adW[1],b[1]:=b[1]−adb[1]
W [ 2 ] : = W [ 2 ] − a d W [ 2 ] , b [ 2 ] : = b [ 2 ] − a d b [ 2 ] W^{[2]}:=W^{[2]}-a dW^{[2]},b^{[2]}:=b^{[2]}-adb^{[2]} W[2]:=W[2]−adW[2],b[2]:=b[2]−adb[2]
正向传播方程为:
forward propageation:
-
z [ 1 ] = W [ 1 ] x + b [ 1 ] z^{[1]}=W^{[1]}x+b^{[1]} z[1]=W[1]x+b[1]
-
a [ 1 ] = σ ( z [ 1 ] ) a^{[1]}=\sigma(z^{[1]}) a[1]=σ(z[1])
-
z [ 2 ] = W [ 2 ] a [ 1 ] + b [ 2 ] z^{[2]}=W^{[2]}a^{[1]}+b^{[2]} z[2]=W[2]a[1]+b[2]
-
a [ 2 ] = g [ 2 ] ( z [ 2 ] ) = σ ( z 2 ) a^{[2]}=g^{[2]}(z^{[2]})=\sigma(z^{{2}}) a[2]=g[2](z[2])=σ(z2)
back propagation:
d
z
[
1
]
=
A
[
2
]
−
Y
,
Y
=
[
y
[
1
]
,
y
[
2
]
,
.
.
.
,
y
[
m
]
]
dz^{[1]}=A^{[2]}-Y,Y=[y^{[1]},y^{[2]},...,y^{[m]}]
dz[1]=A[2]−Y,Y=[y[1],y[2],...,y[m]]
d W [ 2 ] = 1 m d z [ 2 ] A [ 1 ] T dW^{[2]}=\frac{1}{m}dz^{[2]}A^{[1]T} dW[2]=m1dz[2]A[1]T
d b [ 2 ] = 1 m n p . s u m ( d z [ 2 ] , a x i s = 1 , k e e p d i m s = T r u e ) db^{[2]}=\frac{1}{m}np.sum(dz^{[2]},axis=1,keepdims=True) db[2]=m1np.sum(dz[2],axis=1,keepdims=True)
d Z [ 1 ] = W [ 2 ] T d Z [ 2 ] ∗ g [ 1 ] ′ ( Z [ 1 ] ) dZ^{[1]}=W^{[2]T}dZ^{[2]}*g[1]{\prime}(Z^{[1]}) dZ[1]=W[2]TdZ[2]∗g[1]′(Z[1])
对上述公式做维度解释:
d W [ 1 ] = 1 m d z [ 1 ] x T dW^{[1]}=\frac{1}{m}dz^{[1]}x^{T} dW[1]=m1dz[1]xT
d b [ 1 ] = 1 m n p . s u m ( d z [ 1 ] , a x i s = 1 , k e e p i m s = t r u e ) db^{[1]}=\frac{1}{m}np.sum(dz^{[1]},axis=1,keepims=true) db[1]=m1np.sum(dz[1],axis=1,keepims=true)
代码实例:
import numpy as np
import matplotlib.pyplot as plt
import h5py
from h5_utils import load_dataset
#加载数据
train_set_x_orig , train_set_y , test_set_x_orig , test_set_y , classes = load_dataset()
#训练集中图片的数量
m_train=train_set_y.shape[1]
#测试集中图片的数量
m_test=test_set_y.shape[1]
#训练、测试集里面图片的宽度和高度(均为64*64)
num_px=train_set_x_orig.shape[1]
#加载数据的情况;
print("训练集的数量:m_train="+str(m_train))
print("测试集的数量:m_test="+str(m_test))
print("每张图片的宽/高:num_px="+str(num_px))
print("每张图片的大小:("+str(num_px)+","+str(num_px)+",3)")
print("训练集_图片的维数:"+str(train_set_x_orig.shape))
print("训练集_标签的维数:"+str(train_set_y.shape))
print("测试集_图片的维数:"+str(test_set_x_orig.shape))
print("测试集_标签的维数:"+str(test_set_y.shape))
#将训练集的数据的维度降低并转置
train_set_x_flatten = train_set_x_orig.reshape(train_set_x_orig.shape[0],-1).T
#将测试集的维度降低并转置
test_set_x_flatten = test_set_x_orig.reshape(test_set_x_orig.shape[0],-1).T
print("------------------------------------------------------------")
print("训练集降维最后的维度:"+str(train_set_x_flatten.shape))
print("训练集_标签的维数:"+str(train_set_y.shape))
print("测试集降维之后的维数:"+str(test_set_x_flatten.shape))
print("测试集_标签的维数:"+str(test_set_y.shape))
train_set_x=train_set_x_flatten/255
test_set_x=test_set_x_flatten/255
def sigmoid(z):
"""
参数:
z - 任何大小的标量或numpy数组
返回:
s - sigmoid(z)
:param z:
:return:
"""
s=1/(1+np.exp(-z))
return s
def initialize_with_zeros(dim):
"""
此函数为w创建一个维度为(dim,1)的0向量,并将b初始化为0
参数:
dim:想要的w矢量的大小
:param dim:
:return:
w - 维度为(dim,1)的初始化标量
b - 初始化的标量(对应于偏差)
"""
w = np.zeros(shape=(dim,1))
b=0
#使用断言来保证我要的数据是正确的
#w的维度是(dim,1)
assert (w.shape==(dim,1))
#b的类型是float或者int
assert (isinstance(b,float) or isinstance(b,int))
return (w,b)
def propagate(w,b,X,Y):
"""
实现前向和后向传播的成本函数及其梯度
:param w: 权重,大小不等的数组(num_px*num_px*3,1)
:param b: 偏差,一个标量
:param X: 矩阵类型为(num_px*num_px*3,训练数量)
:param Y: 真正的“标签”矢量(如果非猫则为0,如果是猫则为1),矩阵维度为(1,训练数据数量)
:return:
cost - 逻辑回归的负对数似然成本
dw - 相对于w的损失梯度,与w相同的形状
db - 相对于b的损失梯度,与b的形状相同
"""
m = X.shape[1]
#正向传播
A = sigmoid(np.dot(w.T,X)+b)
cost=(-1/m)*np.sum(Y*np.log(A)+(1-Y)*(np.log(1-A)))#计算成本,
#反向传播
dw = (1 / m)*np.dot(X,(A - Y).T)
db = (1 / m)*np.sum(A-Y)
#使用断言确保我的数据是正确的
assert (dw.shape == w.shape)
assert (db.dtype == float)
cost = np.squeeze(cost)
assert (cost.shape == ())
#创建一个字典,把dw,db保存起来
grads = {
"dw" : dw,
"db" : db
}
return (grads,cost)
def optimize(w,b,X,Y,num_iteration,learning_rate,print_cost = False):
"""
此函数通过运行梯度下降算法来优化w和b
参数:
w - 权重,大小不等的数组(num_px * num_px * 3,1)
b - 偏差,一个标量
X - 维度为(num_px * num_px * 3,训练数据的数量)的数组。
Y - 真正的“标签”矢量(如果非猫则为0,如果是猫则为1),矩阵维度为(1,训练数据的数量)
num_iterations - 优化循环的迭代次数
learning_rate - 梯度下降更新规则的学习率
print_cost - 每100步打印一次损失值
返回:
params - 包含权重w和偏差b的字典
grads - 包含权重和偏差相对于成本函数的梯度的字典
成本 - 优化期间计算的所有成本列表,将用于绘制学习曲线。
提示:
我们需要写下两个步骤并遍历它们:
1)计算当前参数的成本和梯度,使用propagate()。
2)使用w和b的梯度下降法则更新参数。
"""
costs = []
for i in range(num_iteration):
grads,cost = propagate(w,b,X,Y)
dw = grads["dw"]
db = grads["db"]
w = w - learning_rate * dw
b = b - learning_rate * db
#记录成本
if i % 100 ==0 :
costs.append(cost)
#打印成本数据
if (print_cost) and (i % 100 ==0):
print("迭代的次数: %i,误差值:%f" %(i,cost))
params = {
"w" : w,
"b" : b
}
grads = {
"dw" : dw,
"db" : db
}
return (params,grads,costs)
def predict(w , b , X ):
"""
使用学习逻辑回归参数logistic (w,b)预测标签是0还是1,
参数:
w - 权重,大小不等的数组(num_px * num_px * 3,1)
b - 偏差,一个标量
X - 维度为(num_px * num_px * 3,训练数据的数量)的数据
返回:
Y_prediction - 包含X中所有图片的所有预测【0 | 1】的一个numpy数组(向量)
"""
m = X.shape[1] #图片的数量
Y_prediction = np.zeros((1,m))
w = w.reshape(X.shape[0],1)
#计预测猫在图片中出现的概率
A = sigmoid(np.dot(w.T , X) + b)
for i in range(A.shape[1]):
#将概率a [0,i]转换为实际预测p [0,i]
Y_prediction[0,i] = 1 if A[0,i] > 0.5 else 0
#使用断言
assert(Y_prediction.shape == (1,m))
return Y_prediction
def model(X_train, Y_train , X_test , Y_test , num_iterations = 2000 ,learning_rate = 0.5 , print_cost = False):
"""
通过调用之前实现的函数来构建逻辑回归模型
参数:
X_train - numpy的数组,维度为(num_px * num_px * 3,m_train)的训练集
Y_train - numpy的数组,维度为(1,m_train)(矢量)的训练标签集
X_test - numpy的数组,维度为(num_px * num_px * 3,m_test)的测试集
Y_test - numpy的数组,维度为(1,m_test)的(向量)的测试标签集
num_iterations - 表示用于优化参数的迭代次数的超参数
learning_rate - 表示optimize()更新规则中使用的学习速率的超参数
print_cost - 设置为true以每100次迭代打印成本
返回:
d - 包含有关模型信息的字典。
"""
w, b = initialize_with_zeros(X_train.shape[0])
parameters, grads, costs = optimize(w, b, X_train, Y_train, num_iterations, learning_rate, print_cost)
# 从字典“参数”中检索参数w和b
w, b = parameters["w"], parameters["b"]
# 预测测试/训练集的例子
Y_prediction_test = predict(w, b, X_test)
Y_prediction_train = predict(w, b, X_train)
# 打印训练后的准确性
print("训练集准确性:", format(100 - np.mean(np.abs(Y_prediction_train - Y_train)) * 100), "%")
print("测试集准确性:", format(100 - np.mean(np.abs(Y_prediction_test - Y_test)) * 100), "%")
d = {
"costs": costs,
"Y_prediction_test": Y_prediction_test,
"Y_prediciton_train": Y_prediction_train,
"w": w,
"b": b,
"learning_rate": learning_rate,
"num_iterations": num_iterations}
return d
d = model(train_set_x, train_set_y, test_set_x, test_set_y, num_iterations=2000, learning_rate=0.005, print_cost=True)
# 绘制图
costs = np.squeeze(d['costs'])
plt.plot(costs)
plt.ylabel('cost')
plt.xlabel('iterations (per hundreds)')
plt.title("Learning rate =" + str(d["learning_rate"]))
plt.show()
运行效果:
绘制图
costs = np.squeeze(d[‘costs’])
plt.plot(costs)
plt.ylabel(‘cost’)
plt.xlabel(‘iterations (per hundreds)’)
plt.title(“Learning rate =” + str(d[“learning_rate”]))
plt.show()
运行效果:
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210428110618806.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzUyMzc3MA==,size_16,color_FFFFFF,t_70)
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210428110618781.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzUyMzc3MA==,size_16,color_FFFFFF,t_70)