张量生成
- 创建一个张量
a = tf.constant([1,5],dtype=tf.int64)
一维张量,俩个元素,1和5
- 将numpy转为tensor
a = np.arange(0,5)
b = tf.convert_to_tensor(a,dtype=tf.int64)
- 创建一个tensor
维度:一维直接写个数,二维用[行,列],多维用[n,m,j,k…]
a = tf.zeros([2,3])
b = tf.ones(4)
c = tf.fill([2,2],9)
#生成正太分布的随机数,默认均值为0,标准差为1
d = tf.random.normal([2,2],mean=0.5,stddev=1)
print(d)
# 生成截断式正太分布的随机数
e = tf.random.truncated_normal([2,2],mean=0.5,stddev=1)
print(e)
# 生成均匀分布随机数,前闭后开区间
f = tf.random.uniform([2,2],minval=1,maxval=2)
TF常用函数
- 强制tensor转换为该数据类型
x1 = tf.constant([1.,2.,3.],dtype=tf.float64)
print(x1)
x2 = tf.cast(x1,tf.int32)
- 计算张量维度上的最小值,最大值
print(tf.reduce_max(x2))
print(tf.reduce_min(x2))
- 理解axis
axis = 0 纵向操作
axis = 1 横向操作
- tf.Variable()将变量标记为”可训练“,被标记的变量会在反向传播中记录梯度信息。神经网络训练中,常用该函数标记待训练参数
w = tf.Variable(tf.random.normal([2,2],mean=0,stddev=1))
- 切分传入张量的第一维度,生成输入特征/标签对,构建数据集
features = tf.constant([12,23,10,17])
labels = tf.constant([0,1,1,0])
dataset = tf.data.Dataset.from_tensor_slices((features,labels))
print(dataset)
- tf.GradientTape()
with结构记录计算过程,gradient求出张量的梯度
loss 函数
w 对谁求导
w2的导数是2w所以是6
with tf.GradientTape() as tape:
w = tf.Variable(tf.constant(3.0))
loss = tf.pow(w,2)
grad = tape.gradient(loss,w)
print(grad)
- enumerate是python的内建函数,它可遍历每个元素(如列表,元组或字符串),组合为:索引 元素,常在for循环中使用
seq = ['one','two','three']
for i,element in enumerate(seq):
print(i,element)
- tf.one_hot()
独热编码:在分类问题中,常用独热码做标签,标记类别:1表示是,0表示非
tf.one_hot(带转换数据,depth = 几分类)
classes = 3
labels = tf.constant([1,0,2])
output = tf.one_hot(labels,depth=classes)
print(output)
- tf.nn.softmax
当n分类的n个输出通过softmax()函数,便符合概率分布了
y = tf.constant([1.01,2.01,-0.66])
y_pro = tf.nn.softmax(y)
print("After softmax,y_pro is",y_pro)
- assign_sub
赋值操作,更新参数的值并返回
调用assign_sub前,先用tf.Variable定义变量w为可训练(可自更新)
w = tf.Variable(4)
w.assign_sub(1)
print(w)
# 3
- tf.argmax(张量名,axis = 操作轴) 0纵向 1横向
返回张量沿指定维度最大值的索引
test = np.array([[1,2,3],[2,3,4],[5,4,3,[8,7,2]]])
print(test)
print(tf.argmax(test,axis=0))
print(tf.argmax(test,axis=1))
神经网络实现鸢尾花分类
背下来
预备知识
- tf.where(条件语句,真返回A,假返回B)
- np.random.RandomState.rand(维度)
返回一个[0,1)之间的随机数
维度为空,返回标量
rdm = np.random.RandomState(seed=1)
a = rdm.rand(1) # 返回一个随机标量
b = rdm.rand(2,3) # 返回维度为2行3列的随机数矩阵
- np.mgrid[起始值:结束值:步长 , …]
- x.ravel() 将x变为一维数组,把.前变量拉直
- np.c_[数组1,数组2,…] 使返回的间隔数值点配对
x,y = np.mgrid[1:3:1,2:4:0.5]
grid = np.c_[x.ravel(),y.ravel()]
print(x)
print(y)
print(grid)
复杂度,学习率
时间复杂度,空间复杂度
学习率:代码每次更新的幅度
指数衰减学习率 = 初始学习率 * 学习率衰减率 ** (当前轮数/多少轮衰减一次)
lr = LR_BASE * LR_DECAY ** (epoch / LR_STEP)
激活函数
- tf.nn.sigmoid(x)
易造成梯度消失
输出非0均值,收敛慢
幂运算复杂,训练时间长
- tf.math.tanh(x)
易造成梯度消失
输出是0均值
幂运算复杂,训练时间长
- tf.nn.relu(x)
优点:解决了梯度消失问题(在正区间)只需;判断输入是否大于0,计算速度快;收敛速度远快于sigmoid和tanh
缺点:输出非0均值,收敛慢;Dead ReIUs问题:某些神经元可能永远不会被激活,导致相应的参数永远不能被更新
- tf.nn.leaky_relu(x) f(x) = max(ax,x)
损失函数
预测值y与已知答案y_的差距
-
均方误差 loss_mse = tf.reduce_mean(tf.square(y_-y))
-
交叉熵损失函数CE 表征俩个概率分布之间的距离
-
- tf.losses.categorical_crossentropy(y_,y)
-
softmax与交叉熵结合
-
- tf.nn.softmax_cross_entropy_with_logits(y_,y)
欠拟合与过拟合
- 欠拟合的解决方法
-
- 增加输入特征项
- 增加网络参数
- 减少正则化参数
- 过拟合的解决方法
-
- 数据清洗
- 增大数据集
- 采用正则化
- 增大正则化参数
- 正则化缓解过拟合
正则化在损失函数中引入模型复杂度指标,利用给w加权值,弱化了训练数据的噪声(一般不正则化b
loss = loss(y与y_) + REGULARIZER * loss(w)
L1正则化大概率会使很多参数变为0,因此该方法可通过稀疏参数,即减少参数的数量,降低复杂度
L2正则化会使参数很接近零但不为0,因此该方法可通过减少参数值的大小降低复杂度
# 采用均方误差损失函数mse = mean(sum(y-out)^2)
loss_mse = tf.reduce_mean(tf.square(y_train - y))
# 添加l2正则化
loss_regularization = []
loss_regularization.append(tf.nn.l2_loss(w1))
loss_regularization.append(tf.nn.l2_loss(w2))
# 求和
loss_regularization = tf.reduce_sum(loss_regularization)
#REGULARIZER = 0.03
loss = loss_mse + 0.03 * loss_regularization
优化器
- SGD
- SGDM,在SGD基础上增加了一阶动量
# sgd-momentun
m_w = beta * m_w + (1 - beta) * grads[0]
m_b = beta * m_b + (1 - beta) * grads[1]
w1.assign_sub(lr * m_w)
b1.assign_sub(lr * m_b)
- Adagrad
v_w, v_b = 0, 0
v_w += tf.square(grads[0])
v_b += tf.square(grads[1])
w1.assign_sub(lr * grads[0] / tf.sqrt(v_w))
b1.assign_sub(lr * grads[1] / tf.sqrt(v_b))
- RMSProp,SGD基础上增加了二阶动量
v_w, v_b = 0, 0
beta = 0.9
# rmsprop
v_w = beta * v_w + (1 - beta) * tf.square(grads[0])
v_b = beta * v_b + (1 - beta) * tf.square(grads[1])
w1.assign_sub(lr * grads[0] / tf.sqrt(v_w))
b1.assign_sub(lr * grads[1] / tf.sqrt(v_b))
- Adam
m_w, m_b = 0, 0
v_w, v_b = 0, 0
beta1, beta2 = 0.9, 0.999
# adam
m_w = beta1 * m_w + (1 - beta1) * grads[0]
m_b = beta1 * m_b + (1 - beta1) * grads[1]
v_w = beta2 * v_w + (1 - beta2) * tf.square(grads[0])
v_b = beta2 * v_b + (1 - beta2) * tf.square(grads[1])
m_w_correction = m_w / (1 - tf.pow(beta1, int(global_step)))
m_b_correction = m_b / (1 - tf.pow(beta1, int(global_step)))
v_w_correction = v_w / (1 - tf.pow(beta2, int(global_step)))
v_b_correction = v_b / (1 - tf.pow(beta2, int(global_step)))
w1.assign_sub(lr * m_w_correction / tf.sqrt(v_w_correction))
b1.assign_sub(lr * m_b_correction / tf.sqrt(v_b_correction))
搭建网络八股sequential
-
第一步:import相关模块,如import tensorflow as tf
-
第二步:指定输入网络的训练集和测试集,如指定训练集的输入x_train和标签y_train,测试集的输入x_test和标签y_test。
-
第三步:逐层搭建网络结构,model = tf.keras.models.Sequential()。
-
第四步:在model.compile()中配置训练方法,选择训练时使用的优化器、损失函数和最终评价指标。
-
第五步:在model.fit()中执行训练过程,告知训练集和测试集的输入值和标签、每个batch的大小(batchsize)和数据集的迭代次数(epoch)
-
第六步:使用model.summary()打印网络结构,统计参数数目。
搭建Model
class IrisModel(Model):
def __init__(self):
super(IrisModel,self).__init__()
self.d1 = Dense(3,activation='sigmoid',kernel_regularizer=tf.keras.regularizers.l2())
def call(self,x):
y = self.d1(x)
return y
model = IrisModel()
断点续训
load_weights(路径中文名) 读取模型
checkpoint_save_path = "./checkpoint/mnist.ckpt"
if os.path.exists(checkpoint_save_path + '.index'):
print('-------------load the model-----------------')
model.load_weights(checkpoint_save_path)
cp_callback = tf.keras.callbacks.ModelCheckpoint(filepath=checkpoint_save_path,
save_weights_only=True,
save_best_only=True)
history = model.fit(x_train, y_train, batch_size=32, epochs=5, validation_data=(x_test, y_test), validation_freq=1,
callbacks=[cp_callback])
参数提取
model.trainable_variables 返回模型中可训练的参数
设置print输出格式
np.set_printoptions(threshold=超过多少省略显示)
np.set_printoptions(threshold=np.inf) # np.inf表示无限大
acc与loss
# 显示训练集和验证集的acc和loss曲线
acc = history.history['sparse_categorical_accuracy']
val_acc = history.history['val_sparse_categorical_accuracy']
loss = history.history['loss']
val_loss = history.history['val_loss']
plt.subplot(1, 2, 1)
plt.plot(acc, label='Training Accuracy')
plt.plot(val_acc, label='Validation Accuracy')
plt.title('Training and Validation Accuracy')
plt.legend()
plt.subplot(1, 2, 2)
plt.plot(loss, label='Training Loss')
plt.plot(val_loss, label='Validation Loss')
plt.title('Training and Validation Loss')
plt.legend()
plt.show()
卷积神经网络
输入特征值的深度(channel数),决定了当前层卷积核的深度
当前层卷积核的个数,决定了当前层输出特征图的深度
感受野
卷积神经网络各输出特征图中的每个像素点,在原始输入图片上映射区域的大小
全零填充
为了保持输出图像尺寸与输入图像一致,经常会在输入图像周围进行全零填充
在Tensorflow框架中,用参数padding = ‘SAME’或padding = ‘VALID’表示是否进行全零填充
TF描述
tf.keras.layers.Conv2D(
input_shape = (高, 宽, 通道数), #仅在第一层有
filters = 卷积核个数,
kernel_size = 卷积核尺寸,
strides = 卷积步长,
padding = ‘SAME’ or ‘VALID’,
activation = ‘relu’ or ‘sigmoid’ or ‘tanh’ or ‘softmax’等
#如有BN则此处不用写
)
BN层
Batch Normalization将神经网络每层的输入都调整到均值为0,方差为1的标准正态分布,其目的是解决神经网络中梯度消失的问题
BN操作的另一个重要步骤是缩放和偏移,值得注意的是,缩放因子γ以及偏移因子β都是可训练参数
tf.keras.layers.BatchNormalization()
池化
池化的作用是减少特征数量(降维)。最大值池化可提取图片纹理,均值池化可保留背景特征
tf.keras.layers.MaxPool2D(
pool_size = 池化核尺寸,
strides = 池化步长,
padding = ‘SAME’ or ‘VALID’
)
tf.keras.layers.AveragePooling2D(
pool_size = 池化核尺寸,
strides = 池化步长,
padding = ‘SAME’ or ‘VALID’
)
舍弃
在神经网络的训练过程中,将一部分神经元按照一定概率从神经网络中暂时舍弃,使用时被舍弃的神经元恢复链接
tf.keras.layers.Dropout(0.2) #dropout
循环神经网络
参数时间共享,循环层提取时间信息
循环神经网络:借助循环核提取时间特征后,送入全连接网络
循环计算层:向输出方向生长
return_sequences = False 循环核仅在最后一刻输出ht
Embedding:一种单词编码方法,用低维向量实现了编码。这种编码通过神经网络训练优化,能表达出单词间的相关性s