1.膜电极参数优化
1.导入数据
1.导入数据
import pandas as pd
df = pd.read_csv('MEA.csv',encoding = 'gbk') #导入数据,使用GBK编码
print(df)
2.设置输入输出
import numpy as np
for i in range(2): #进行两次神经网络
x = df.iloc[:, :-2].values # 设置输入输出,x为第1列到倒数第2列,iloc()通过行列号提取数据
if i:
y = df['Pt Consumption per kW@0.65V (mgpt kW-1)'].values
else:
y = df['Power Density at 0.6V (mW cm-2)'].values
x_s = (x-np.mean(x,axis = 0))/np.std(x,axis = 0) #数据标准化,原数据减平均值后除标准差,axis=0按列计算,np.std()计算标准差
y_s = (y-np.mean(y))/np.std(y)
print(x_s,y_s)
3.划分数据集
from sklearn.model_selection import train_test_split
x_train,x_test,y_train,y_test= train_test_split(x_s,y_s, #数据集分割训练和测试,检验占比0.15,随机种子91
test_size = 0.15,
random_state = 91)
2.模型构建
1.模型构建
import tensorflow as tf
from tensorflow import keras
model = keras.Sequential( #构建神经网络
[
keras.Input(shape = (19)),
keras.layers.Dense(300,activation = 'relu',
kernel_initializer = 'random_normal', #权重初始化,随机正态分布
bias_initializer = 'random_normal', #偏移量初始化
kernel_regularizer = keras.regularizers.l2(0.001)), #权重正则化,L2正则化
keras.layers.Dropout(0.1), #丢弃法,每次更新丢掉0.1的神经元
keras.layers.Dense(300, activation = 'relu',
kernel_initializer = 'random_normal',
bias_initializer = 'random_normal',
kernel_regularizer = keras.regularizers.l2(0.001)),
keras.layers.Dropout(0.1),
keras.layers.Dense(1)
]
)
print(model.summary())
adam = keras.optimizers.Adam(learning_rate = 0.001) #设置学习率
model.compile(loss = 'mse',optimizer = adam)
early_stopping = keras.callbacks.EarlyStopping(monitor = 'val_loss', #设置提前终止
patience = 20)
history = keras.callbacks.History() #记录模型
checkpointer = keras.callbacks.ModelCheckpoint(filepath = 'weights.hdf5',
save_best_only = True) #保存模型,保存最好的
model.fit(x_train,y_train,validation_split = 0.2,epochs = 650, #validation_split 从测试集中划分多少比例给训练集
batch_size = 16,verbose = 0,callbacks = [early_stopping])
2.参数初始化
zeros:全零初始化
random_normal:随机正态分布
random_uniform:随机均匀分布
glorot_normal:Glorot正态分布
glorot_uniform:Glorot均匀分布(默认)
he_uniform:何恺明均匀分布
3.预防过拟合
1.增加数据
2.减小网络容量
3.Dropout
丢弃法:每次更新时,将神经元按比率随机丢弃。
4.权重正则化
5.Mini Batch
全梯度下降 | 随机梯度下降 | |
---|---|---|
收敛速度 | 慢 | 快 |
并行性 | 可并行 | 无法并行 |
折中方法:mini Batch
学习率和样本数量需手动预先指定,不需要通过模型训练得到。
model.fit()中参数batch_size,用于控制拟合过程的输出,默认32,减小会降低过拟合风险,增大会提高收敛稳定性。
6.提前终止
EarlyStopping,所监测的指标不再提升时,停止训练。
keras.callbacks.EarlyStopping(monitor = ‘val_loss’,min_delta = 0,patience = 0,mode = ‘auto’)
monitor:监测指标,‘acc’,‘val_acc’,‘loss’,‘val_loss’
min_delta:阈值
patience:耐心值,容忍多少个epoch内没有提升
mode:模式,‘auto’,‘min’,‘max’
回调函数(Callbacks)
函数合集,可用来查看训练模型的内在状态和统计,并控制回归进程。
常用的回调函数,EarlyStopping,History,ModelCheckpoint
4.回归过程与结果可视化
1.绘制loss的训练变化图
#绘制损失值的训练变化图
import matplotlib.pyplot as plt
plt.plot(history.history['loss']) #训练集损失值
plt.plot(history.history['val_loss']) #测试集损失值
plt.title('Model loss') #标题
plt.ylabel('Loss') #x标签,损失值
plt.xlabel('Epoch') #y标签,训练次数
plt.legend(['Train','Val']) #图例
plt.show()
2.输出回归模型的评价指标
from sklearn.metrics import r2_score
#回归结果展示
result_train = model.predict(x_train) #预测值
result_test = model.predict(x_test)
y_pred_train = result_train * np.std(y)+np.mean(y) #逆标准化,预测值
y_real_train = y_train * np.std(y)+np.mean(y) #真实值
y_pred_train = y_pred_train.reshape(-1) #一列变为一行
y_pred_test = result_test * np.std(y)+np.mean(y) #逆标准化,预测值
y_real_test = y_test * np.std(y)+np.mean(y) #真实值
y_pred_test = y_pred_test.reshape(-1) #一列变为一行
def compute_mae_mse_rmse(pred,real): #自定义计算平均绝对误差mae,均方误差mse,均方根误差rmse,R方r2
error = []
for j in range(len(real)):
error.append(real[j]-pred[j]) #预测值与真实值之差
error_squared = []
error_abs = []
for val in error:
error_squared.append(val*val) #误差平方
error_abs.append(abs(val)) #误差绝对值
mae = sum(error_abs)/len(error_abs) #MAE
mse = sum(error_squared)/len(error_squared) #MSE
rmse = np.sqrt(mse) #均方根误差rmse是均方误差mse的算术平方根
r2 = r2_score(real,pred) #评价回归模型,r2->1,模型越好
return mae,mse,rmse,r2
error_val_train = compute_mae_mse_rmse(y_pred_train,y_real_train) #计算误差
error_val_test = compute_mae_mse_rmse(y_pred_test,y_real_test)
print('training mae: %.2f,mse: %.2f,rmse: %.2f,r2: %.4f'%(error_val_train[0],error_val_train[1], #输出预测的误差
error_val_train[2],error_val_train[3]))
print('testing mae: %.2f,mse: %.2f,rmse: %.2f,r2: %.4f'%(error_val_test[0],error_val_test[1],
error_val_test[2],error_val_test[3]))
3.绘制真实—预测对比图
#绘制回归结果展示,横坐标预测值,纵坐标真实值
plt.figure(figsize = (8,6)) #设置画图大小
plt.scatter(y_pred_train,y_real_train,color = 'blue',
label = 'Artificial Neural Network Traing Set',alpha = 0.25,marker = '^') #散点图,蓝色三角代表训练集,alpha散点透明度
plt.scatter(y_pred_test,y_real_test,color = 'red',
label = 'Artificial Neural Network Test Set',alpha = 0.75) #散点图,红色圆点代表测试集
plt.legend() #图例
if i: #设置横纵轴标签
plt.xlabel('Predicted Pt Consumption per kW@0.65V (mgpt kW-1)')
plt.ylabel('Real Pt Consumption per kW@0.65V (mgpt kW-1)')
xx = np.arange(0, 2.5, 0.005)
yy = np.arange(0, 2.5, 0.005)
plt.plot(xx, yy) # 绘制对角线
else:
plt.xlabel('Predicted Power Density at 0.6 (mW cm-2)')
plt.ylabel('Real Power Density at 0.6 (mW cm-2)')
xx = np.arange(0, 1200, 0.1)
yy = np.arange(0, 1200, 0.1)
plt.plot(xx, yy) # 绘制对角线
plt.show()
5.模型保存与加载
model.save('model.h5') #保存模型
model_load = keras.model.load_model('model.h5') #模型加载
1.模型保存
model.save()
将模型保存为.h5或者.hdf5文件
HDF:Hierarchical Data Format(分层数据格式)
2.权重正则化
1.权重可视化
import tensorflow as tf
from tensorflow import keras
import numpy as np
import matplotlib.pyplot as plt
mnist = keras.datasets.mnist #导入mnist数据集
(train_images,train_labels),(test_images,test_labels) = mnist.load_data() #数据集分为训练集和测试集
train_images,test_images = train_images/255.0,test_images/255.0 #数据范围0-1
model_0 = keras.Sequential( #初始模型
[
keras.layers.Flatten(input_shape=(28,28)),
keras.layers.Dense(10,activation = 'softmax',use_bias = False) #输出层
]
)
model_0.compile(optimizer = 'adam',
loss = 'sparse_categorical_crossentropy',
metrics = ['accuracy'])
w0 = model_0.get_weights()[0] #获取初始权重
fig,axs = plt.subplots(2,5,figsize = (15,5)) #绘制子图,画布大小15*5
for i in range(10):
w2p = w0[:,i].reshape(28,28)
axs[int(i/5),i%5].imshow(w2p) #axs[i,j]位于第i行第j列
plt.show()
model_0.fit(train_images,train_labels,epochs = 10) #训练10次
w0 = model_0.get_weights()[0] #获取训练后权重
fig,axs = plt.subplots(2,5,figsize = (15,5)) #绘制子图,画布大小15*5
for i in range(10):
w2p = w0[:,i].reshape(28,28)
axs[int(i/5),i%5].imshow(w2p) #axs[i,j]位于第i行第j列
plt.show()
2.正则化
对于一个神经网络模型,参数非常多,很容易造成过拟合。
解决方案:将参数个数考虑到损失函数中
m
i
n
w
=
(
1
2
n
∥
X
w
−
y
∥
2
2
+
α
∥
w
∥
0
)
,
∥
w
∥
0
w
中非
0
元素的个数
\underset{w}{min}=\left(\frac{1}{2n}\left\|X_{w}-y\right\|_{2}^{2}+\alpha\left\|w\right\|_{0}\right) ,\left\|w\right\|_{0} w中非0元素的个数
wmin=(2n1∥Xw−y∥22+α∥w∥0),∥w∥0w中非0元素的个数
3.L1正则化
套索回归(Lasso回归)
m
i
n
w
=
(
1
2
n
∥
X
w
−
y
∥
2
2
+
α
∥
w
∥
1
)
,其中
∥
w
∥
1
=
∑
i
∣
w
i
∣
\underset{w}{min}=\left(\frac{1}{2n}\left\|X_{w}-y\right\|_{2}^{2}+\alpha\left\|w\right\|_{1}\right),其中\left\|w\right\|_{1}=\sum_{i}\left|w_{i}\right|
wmin=(2n1∥Xw−y∥22+α∥w∥1),其中∥w∥1=i∑∣wi∣
#L1正则化
model_1 = keras.Sequential( #初始模型
[
keras.layers.Flatten(input_shape=(28,28)),
keras.layers.Dense(10,kernel_regularizer = keras.regularizers.l1(0.05), #L1正则化
activation = 'softmax',use_bias = False) #输出层
]
)
model_1.compile(optimizer = 'adam',
loss = 'sparse_categorical_crossentropy',
metrics = ['accuracy'])
w0 = model_1.get_weights()[0] #获取初始权重
fig,axs = plt.subplots(2,5,figsize = (15,5)) #绘制子图,画布大小15*5
for i in range(10):
w2p = w0[:,i].reshape(28,28)
axs[int(i/5),i%5].imshow(w2p) #axs[i,j]位于第i行第j列
plt.show()
model_1.fit(train_images,train_labels,epochs = 10) #训练10次
w0 = model_1.get_weights()[0] #获取训练后权重
fig,axs = plt.subplots(2,5,figsize = (15,5)) #绘制子图,画布大小15*5
for i in range(10):
w2p = w0[:,i].reshape(28,28)
axs[int(i/5),i%5].imshow(w2p) #axs[i,j]位于第i行第j列
plt.show()
4.L2正则化
岭回归(Ridge回归)
m
i
n
w
=
(
1
2
n
∥
X
w
−
y
∥
2
2
+
α
∥
w
∥
2
)
,其中
∥
w
∥
2
=
∑
i
w
i
2
\underset{w}{min}=\left(\frac{1}{2n}\left\|X_{w}-y\right\|_{2}^{2}+\alpha\left\|w\right\|_{2}\right),其中\left\|w\right\|_{2}=\sum_{i}\sqrt{w_{i}^{2}}
wmin=(2n1∥Xw−y∥22+α∥w∥2),其中∥w∥2=i∑wi2
#L2正则化
model_2 = keras.Sequential( #初始模型
[
keras.layers.Flatten(input_shape=(28,28)),
keras.layers.Dense(10,kernel_regularizer = keras.regularizers.l2(0.05), #L1正则化
activation = 'softmax',use_bias = False) #输出层
]
)
model_2.compile(optimizer = 'adam',
loss = 'sparse_categorical_crossentropy',
metrics = ['accuracy'])
w0 = model_2.get_weights()[0] #获取初始权重
fig,axs = plt.subplots(2,5,figsize = (15,5)) #绘制子图,画布大小15*5
for i in range(10):
w2p = w0[:,i].reshape(28,28)
axs[int(i/5),i%5].imshow(w2p) #axs[i,j]位于第i行第j列
plt.show()
model_2.fit(train_images,train_labels,epochs = 10) #训练10次
w0 = model_2.get_weights()[0] #获取训练后权重
fig,axs = plt.subplots(2,5,figsize = (15,5)) #绘制子图,画布大小15*5
for i in range(10):
w2p = w0[:,i].reshape(28,28)
axs[int(i/5),i%5].imshow(w2p) #axs[i,j]位于第i行第j列
plt.show()