我在完成吴恩达深度学习L1W4的时完成的神经网络cost下降缓慢,在调整lr后会趋于一条直线
import numpy as np
import h5py
import matplotlib.pyplot as plt
import scipy
from PIL import Image
from scipy import ndimage
%matplotlib inline
plt.rcParams['figure.figsize'] = (5.0, 4.0) # 设置最大图像大小
plt.rcParams['image.interpolation'] = 'nearest'
plt.rcParams['image.cmap'] = 'gray'
%load_ext autoreload
%autoreload 2
np.random.seed(1)
ef sigmoid(Z):
A = 1/(1+np.exp(-Z))
cache = Z
return A, cache
def relu(Z):
A = np.maximum(0,Z)
assert(A.shape == Z.shape)
cache = Z
return A, cache
def initialize_parameters_deep(layer_dims):
"""参数初始化
layer_dims -- 列表,存储了每层的单元数(特征数),从A[0]开始(X)"""
np.random.seed(3)
parameters = {} #使用字典来存储初始化好的参数
L = len(layer_dims)
for l in range(1, L):
parameters["W" + str(l)] = np.random.randn(layer_dims[l], layer_dims[l - 1]) * 0.01
parameters["b" + str(l)] = np.zeros((layer_dims[l], 1))
assert(parameters['W' + str(l)].shape == (layer_dims[l], layer_dims[l - 1]))
assert(parameters['b' + str(l)].shape == (layer_dims[l], 1))
return parameters
#下面进行前向传播模型的建立,包括以下
#1.实现线性部分
#2.使用激活函数(ReLU 或 sigmoid)
#3.应用到整个模型
def linear_forward(A, W, b):
"""
前向传播线性模型
A -- 上一层的结果
W, b -- 本层的参数
"""
Z = np.dot(W, A) + b
assert(Z.shape == (W.shape[0], A.shape[1]))
cache = (A, W, b)
return Z, cache
def linear_activation_forward(A_prev, W, b, activation):
"""
激活函数
A_prev -- 表示上一层的结果
W, b -- 本层的参数
activation -- 表示激活函数(ReLU 或 sigmoid)
"""
if activation == "sigmoid":
Z, linear_cache = linear_forward(A_prev, W, b)
A, activation_cache = sigmoid(Z)
elif activation == "relu":
Z, linear_cache = linear_forward(A_prev, W, b)
A, activation_cache = relu(Z)
assert (A.shape == (W.shape[0], A_prev.shape[1]))
cache = (linear_cache, activation_cache)
return A, cache
def L_model_forward(X, parameters):
"""
L层模型的实现
X -- 测试集
parameters -- 参数集(w,b)
"""
caches = []
L = len(parameters) // 2 #计算共有几层
A = X
for l in range(1, L):
A_prev = A
A, cache = linear_activation_forward(A_prev, parameters["W" + str(l)], parameters["b" + str(l)], activation = "relu")
caches.append(cache)
AL, cache = linear_activation_forward(A, parameters["W" + str(L)], parameters["b" + str(L)], activation = "sigmoid")
caches.append(cache)
assert(AL.shape == (1, X.shape[1]))
return AL, caches
def compute_cost(AL, Y):
"""
计算代价函数
AL -- Y_hat
Y -- Y
"""
m = Y.shape[1]
cost = - (1 / m) * np.sum(np.multiply(Y, np.log(AL)) + np.multiply(1 - Y, np.log(1 - AL)))
cost = np.squeeze(cost)
assert(cost.shape == ())
return cost
#接下来是反向传播模型,包括如下
#1.线性部分
#2.激活函数部分
#3.整合到L层
#4.更新参数
def liner_backward(dZ, cache):
A_prev, W, b = cache
m = A_prev.shape[1]
dW = (1 / m) * np.dot(dZ, A_prev.T)
db = (1 / m) * np.sum(dZ, axis = 1, keepdims=True)
dA_prev = np.dot(W.T, dZ)
assert (dA_prev.shape == A_prev.shape)
assert (dW.shape == W.shape)
assert (db.shape == b.shape)
return dA_prev, dW, db
def relu_backward(dA, cache):
Z = cache
dZ = np.array(dA, copy=True) # just converting dz to a correct object.
# When z <= 0, you should set dz to 0 as well.
dZ[Z <= 0] = 0
assert (dZ.shape == Z.shape)
return dZ
def sigmoid_backward(dA, cache):
Z = cache
s = 1/(1+np.exp(-Z))
dZ = dA * s * (1-s)
assert (dZ.shape == Z.shape)
return dZ
def liner_activation_backward(dA, cache, activation):
"""
整合线性部分和激活函数部分
dA -- 上一层的输入
cache -- 计算梯度所需要的参数
activation -- relu or sigmoid
"""
linear_cache, activation_cache = cache #liner(W,b,A_prev) ac(Z)
if activation == "relu":
dZ = relu_backward(dA, activation_cache)
dA_prev, dW, db = liner_backward(dZ, linear_cache)
elif activation == "sigmoid":
dZ = sigmoid_backward(dA, activation_cache)
dA_prev, dW, db = liner_backward(dZ, linear_cache)
return dA_prev, dW, db
def L_model_backward(AL, Y, caches):
"""
这是一个L层模型的反向传播模型
AL -- Y_hat
Y -- label
caches -- 参数的列表,每个元素包含线性的缓存和激化函数的缓存
"""
grads = {}
L = len(caches)
m = AL.shape[1]
Y = Y.reshape(AL.shape) #因为Y是一个列向量,而AL是一个行向量
#首先要计算dAL,它是cost函数的关于AL的导数
dAL = - np.divide(Y, AL) + np.divide(1 - Y, 1 - AL)
#接下来计算输出层(sigmoid)的导数
cache = caches[L - 1]
grads["dA" + str(L-1)],grads["dW" + str(L)],grads["db" + str(L)] = liner_activation_backward(dAL, cache, activation = "sigmoid")
#接下来是线性部分的导数计算
for l in reversed(range(L-1)):
cache = caches[l]
dA_prev_temp, dW_temp, db_temp = liner_activation_backward(grads["dA" + str(l + 1)], cache, activation = "relu")
grads["dA" + str(l)] = dA_prev_temp
grads["dW" + str(l + 1)] = dW_temp
grads["db" + str(l + 1)] = db_temp
return grads
def update_parameters(parameters, grads, learning_rate):
"""
这是参数更新函数
parameters -- W, b的参数列表
grads -- 梯度列表
learning_rate -- 学习率
"""
L = len(parameters) // 2
for l in range(L):
parameters["W" + str(l + 1)] = parameters["W" + str(l + 1)] - grads["dW" + str(l + 1)] * learning_rate
parameters["b" + str(l + 1)] = parameters["b" + str(l + 1)] - grads["db" + str(l + 1)] * learning_rate
return parameters
def load_dataset():
# 保存的是训练集里面的图像数据(本训练集有209张64x64的图像)。
# 保存的是训练集的图像对应的分类值(【0 | 1】,0表示不是猫,1表示是猫)。
train_dataset = h5py.File('D:/ML/PYTHON/train_catvnoncat.h5', "r")
train_set_x_orig = np.array(train_dataset["train_set_x"][:]) # your train set features
train_set_y_orig = np.array(train_dataset["train_set_y"][:]) # your train set labels
# 保存的是测试集里面的图像数据(本训练集有50张64x64的图像)。
# 保存的是测试集的图像对应的分类值(【0 | 1】,0表示不是猫,1表示是猫)
test_dataset = h5py.File('D:/ML/PYTHON/test_catvnoncat.h5', "r")
test_set_x_orig = np.array(test_dataset["test_set_x"][:]) # your test set features
test_set_y_orig = np.array(test_dataset["test_set_y"][:]) # your test set labels
# 保存的是以bytes类型保存的两个字符串数据,数据为:[b’non-cat’ b’cat’]。
classes = np.array(test_dataset["list_classes"][:]) # the list of classes
train_set_y_orig = train_set_y_orig.reshape((1, train_set_y_orig.shape[0]))
test_set_y_orig = test_set_y_orig.reshape((1, test_set_y_orig.shape[0])) #转置成为1个行向量
return train_set_x_orig, train_set_y_orig, test_set_x_orig, test_set_y_orig, classes
train_set_x , train_set_y , test_set_x , test_set_y , classes = load_dataset() # 加载数据集
def data_pre(train,test):
train_ = train.reshape(train.shape[0],-1).T
test_ = test.reshape(test.shape[0],-1).T
train = train_ / 255
test = test_ / 255
return train,test
train_set_x, test_set_x = data_pre(train_set_x, test_set_x)
layers_dims = [12288, 20, 7, 5, 1] # 5-layer model
ef L_layer_model(X, Y, layers_dims, learning_rate = 0.0075, num_iterations = 3000, print_cost = False):
"""
这是一个猫分类的二分类模型
输入:
X -- 测试集数据
Y -- 测试集标签
layers_dims -- 神经网络维数情况
learning_rate -- 学习率
num_iterations -- 遍历次数
print_cost -- 是否将学习情况打印
输出:
将学习好的参数装在parameters字典中返回
"""
np.random.seed(1)
costs = []
#参数初始化
parameters = initialize_parameters_deep(layers_dims)
#遍历开始
for i in range(0, num_iterations):
#进行正向传播
AL, caches = L_model_forward(X, parameters)
#计算代价函数
cost = compute_cost(AL, Y)
#计算梯度
grads = L_model_backward(AL, Y, caches)
#更新参数
parameters = update_parameters(parameters, grads, learning_rate = learning_rate)
if print_cost and i % 100 == 0:
print("Cost after iteration %i: %f" %(i, cost))
if print_cost and i % 100 == 0:
costs.append(cost)
plt.plot(np.squeeze(costs))
plt.ylabel('cost')
plt.xlabel('iterations (per tens)')
plt.title("Learning rate =" + str(learning_rate))
plt.show()
return parameters
parameters = L_layer_model(train_set_x, train_set_y, layers_dims, num_iterations = 2500, print_cost = True)
下面是运行结果
你把网络w的初始化方式改下,我没有按老师那样将输入层也放在里面,所以做了修改:
import numpy as np
import h5py
import matplotlib.pyplot as plt
# 设置一些画图相关的参数
%matplotlib inline
plt.rcParams['figure.figsize'] = (5.0, 4.0)
plt.rcParams['image.interpolation'] = 'nearest'
plt.rcParams['image.cmap'] = 'gray'
#与file_1st一样先加载数据集并规范化处理特征
def load_data():
train_dataset=h5py.File('datasets/train_catvnoncat.h5','r')
train_set_x_orig=np.array(train_dataset['train_set_x'][:]) #训练集的特征
train_set_y_orig=np.array(train_dataset['train_set_y'][:]) #训练集的标签
train_set_y_orig=train_set_y_orig.reshape((1,train_set_y_orig.shape[0])) #将标签从列向量拉成行向量
test_dataset=h5py.File('datasets/test_catvnoncat.h5','r')
test_set_x_orig=np.array(test_dataset['test_set_x'][:]) #测试集的特征
test_set_y_orig=np.array(test_dataset['test_set_y'][:]) #测试集真正的标签
test_set_y_orig=test_set_y_orig.reshape((1,test_set_y_orig.shape[0])) #将标签从列向量拉成行向量
train_set_x_orig_flatten=train_set_x_orig.reshape(train_set_x_orig.shape[0], -1).T #将特征扁平化,每列是一个样本的特征
test_set_x_orig_flatten=test_set_x_orig.reshape(test_set_x_orig.shape[0],-1).T #特征扁平化
train_set_x=train_set_x_orig_flatten/255 #让特征值在0~1内,利于学习
test_set_x=test_set_x_orig_flatten/255
classes=np.array(test_dataset['list_classes'][:]) #标签的意思,1有猫,0无猫
return train_set_x,train_set_y_orig,test_set_x,test_set_y_orig,classes
#加载数据集得到训练集、测试集的特征与标签 ,每列是一个样本
train_x, train_y, test_x, test_y, classes = load_data()
print('train set shape:'+str(train_x.shape)+' test set shape:'+str(test_x.shape))
np.random.seed(1)
#跟上一节一样先定义模型初始化参数
#feature_length:初始特征个数,layerdim:是一个数组,表示隐藏层每层多少个神经元,根据它们初始化权重w 和 b ,随机数*0.01。
def initilize_parameters(feature_length,layerdim):
cell_in_size=feature_length
paras={}
np.random.seed(1)
layernum=len(layerdim)#多少隐藏层
cell_in_size=feature_length
for layeri in range(layernum):
cell_out_size=layerdim[layeri] #当前第layeri隐藏层 有cell_out_size个神经元
paras['W'+str(layeri)]=(np.random.randn(cell_out_size,cell_in_size))/ np.sqrt(cell_in_size) #延缓梯度消失/爆炸
paras['b'+str(layeri)]=np.zeros((cell_out_size,1))
cell_in_size=cell_out_size #下一层的输入size
return paras
#前向传播时的 某一层的中间各结果
def linear_forward(A_lastlayer,activation,W_thislayer,b_thislayer):
Z_thislayer=np.dot(W_thislayer,A_lastlayer)+b_thislayer
if activation=='sigmoid':
A_thislayer=1/(1+np.exp(-Z_thislayer))
if activation=='relu':
A_thislayer=np.maximum(0,Z_thislayer)
cache_thislayer=(A_lastlayer,W_thislayer,b_thislayer,Z_thislayer,A_thislayer)
return cache_thislayer
#计算成本
def compute_cost(AL,Y):
num=Y.shape[1]
costlast=(-1/num)*np.sum(np.multiply(Y,np.log(AL))+np.multiply(1-Y,np.log(1-AL)))
costlast = np.squeeze(costlast)# 确保cost是一个数值而不是一个数组的形式
return costlast
#现在可以搭建模型了 多层、深度神经网络
def L_model_forward(X,paras):
layernum= len(paras) // 2
caches=[] #用于存所有层 的 所有中间结果
A_lastlayer=X
for layeri in range(layernum):
if layeri==layernum-1:
active='sigmoid'
else:
active='relu' #前面的所有层都用relu激活,最后一层才用sigmoid
Wi=paras['W'+str(layeri)]
bi=paras['b'+str(layeri)]
cache_thislayer=linear_forward(A_lastlayer,active,Wi,bi)
caches.append(cache_thislayer)
A_lastlayer=cache_thislayer[4] #[A_thislayer] #这一层的结果作为下一层的输入
return A_lastlayer,caches
#接下来开始反向传播
def linear_backward(A_lastlayer,Y,cache):
grads={}
layernum=len(cache)
Y = Y.reshape(A_lastlayer.shape) # 让真实标签的维度和预测标签的维度一致
samplenum=Y.shape[1]
for layeri in range(layernum):
lay_i=layernum-1-layeri #因为是反向,从最后一层慢慢往前
A_layi_1,W_layi,b_layi,Z_layi,A_layi=cache[lay_i] #这一层的各个结果
if lay_i==layernum-1:
dZ_layi=A_layi-Y #这是最后一层 sigmoid偏导
else:
reluback = np.zeros(Z_layi.shape)
reluback[Z_layi <= 0] = 0
reluback[Z_layi > 0] = 1
dZ_layi=reluback*dA_layi_1 #除开最后一层的其它层 relu偏导
dA_layi_1=np.dot(W_layi.T,dZ_layi)
dW_layi=(1/samplenum)*np.dot(dZ_layi,A_layi_1.T)
db_layi=(1/samplenum)*np.sum(dZ_layi,axis=1,keepdims=True)
grads['dW'+str(lay_i)]=dW_layi #dW、db所有隐藏层都有
grads['db'+str(lay_i)]=db_layi
if lay_i>0:
grads['dA'+str(lay_i)]=dA_layi_1 #第一层没有dA,其它层都有dA
return grads
#更新参数W b
def update_parameters(paras,grads,lr):
layernum= len(paras) // 2
for lay_i in range(layernum):
paras['W'+str(lay_i)]=paras['W'+str(lay_i)]-lr*grads['dW'+str(lay_i)]
paras['b'+str(lay_i)]=paras['b'+str(lay_i)]-lr*grads['db'+str(lay_i)]
return paras
#演示完整的前向传播与反向传播过程,训练出最好的模型
def dnn_model(X, Y, layers_dims, learning_rate=0.0075, num_iterations=3000, print_cost=False):
costs=[] #用于存放需要画图的成本值
np.random.seed(1)
feature_length=X.shape[0]
paras=initilize_parameters(feature_length,layers_dims)
for i in range(num_iterations):
#先前向传播
lastA,midresults=L_model_forward(X,paras)
#计算此次的成本值
costi=compute_cost(lastA,Y)
if i%200==0 and print_cost:
print('the %i th time,cost is %f'%(i,costi))
costs.append(costi)
#再反向传播 计算梯度
#print('lastA shape:'+str(lastA.shape)+' real label shape:'+str(Y.shape))
grads=linear_backward(lastA,Y,midresults)
#更新参数
#print('iteration:'+str(i)+' dW:'+str(grads['dW'+str(i)].shape)+' db:'+str(grads['db'+str(i)].shape))
#print('iteration:'+str(i)+' W:'+str(paras['W'+str(i)].shape)+' b:'+str(paras['b'+str(i)].shape))
paras=update_parameters(paras,grads,learning_rate)
# 画出成本曲线图
#plt.plot(np.squeeze(costs))
#plt.ylabel('cost')
#plt.xlabel('iterations (per tens)')
#plt.title("Learning rate =" + str(learning_rate))
#plt.show()
return paras
#测试准确率的函数
def predict(x_fea,paras,y_label):
num=y_label.shape[1]
modellabel=np.zeros((1,num))
modelresult,mid_results=L_model_forward(x_fea,paras)
for i in range(num):
if modelresult[0,i]>0.5:
modellabel[0,i]=1
else:
modellabel[0,i]=0
ratio=np.sum((modellabel== y_label) / num)
return ratio
#测试上面编写的完整的网络,喂入数据
layers_dims = [20, 7, 5, 1] #所有隐藏层
bestmodel = dnn_model(train_x, train_y, layers_dims, num_iterations=2000, print_cost=True)
trainratio=predict(train_x,bestmodel,train_y)
testratio=predict(test_x,bestmodel,test_y)
print('train准确率:'+str(trainratio)+' ; test准确率:'+str(testratio))
你可以看下跑的结果,和老师一样 https://blog.csdn.net/wd1603926823/article/details/125183819
问题回答:
Dropout是一种常用的正则化技术,可以有效避免过拟合问题,增加模型的泛化能力。在每次的训练过程中,Dropout随机地移除某些神经元,使得神经网络的每次结构都不同,在整个过程中相当于训练了很多个不同的神经网络,从而可以实现综合取平均的效果,有效避免过拟合问题。
针对该问题,可以采用以下方案进行优化:
使用dropout技术进行正则化,防止过拟合问题。在每个隐藏层设置一个概率数p,每个神经元的被保留的概率就是p,而被删除的概率就是(1-p)。可以在模型训练的过程中使用dropout技术,每次训练时随机地移除一些神经元,增加模型的泛化能力。
进行数据清洗,处理缺失值、异常值等问题,保证数据的完整性和正确性。可以采用标准化、归一化等方法进行数据处理,提高模型的稳定性和精度。
调整模型架构,增加网络层数,优化激活函数、优化器等参数设置,提高模型的性能和泛化能力。可以使用批归一化方法来优化模型性能,降低模型中的内部协方差移动问题,提高精度。
进行交叉验证,验证模型的性能和泛化能力,避免过拟合问题。可以使用k折交叉验证方法进行模型验证和评估,选择最优的模型参数和模型架构,提高模型的泛化能力。
注意模型的特点和任务特性,针对不同的任务进行模型选择和优化。可以针对不同的任务选择合适的模型类型和结构,选择适合的损失函数和优化器,提高模型的效率和精度。
代码示例:
以下是一个示例代码,演示如何在keras框架中使用dropout技术进行正则化:
from keras.models import Sequential
from keras.layers import Dense, Dropout
from keras.optimizers import SGD
# 创建一个Sequential模型
model = Sequential()
# 添加一个隐藏层,设置神经元个数为64,使用relu激活函数
model.add(Dense(64, input_dim=100, activation='relu'))
# 添加一个dropout层,设置概率为0.5
model.add(Dropout(0.5))
# 添加一个输出层,设置神经元个数为10,使用softmax激活函数
model.add(Dense(10, activation='softmax'))
# 定义优化器,学习率为0.01
sgd = SGD(lr=0.01, decay=1e-6, momentum=0.9, nesterov=True)
# 编译模型,设置损失函数、优化器和评估指标
model.compile(loss='categorical_crossentropy', optimizer=sgd, metrics=['accuracy'])
# 训练模型,设置训练集和测试集,设置迭代次数epoch,批处理大小batch_size
model.fit(x_train, y_train, epochs=20, batch_size=128, validation_data=(x_test, y_test))
该代码使用了一个包含一个隐藏层和一个输出层的神经网络,使用了dropout技术进行正则化。具体可以参考keras官网的文档:https://keras.io/layers/core/#dropout