![](https://img.haomeiwen.com/i27579716/4cf444cfb7f1e1c5.png)
tensor和简单运算
# 随机初始化服从正态分布的tensor
t = tf.random.normal(shape=[2, 5], mean=0.0, stddev=0.01, dtype=tf.float32)
t =tf.zeros(shape=[2, 5], dtype=tf.float32)
# List构建tensor
list = [[1, 2, 3], [4, 5, 6]]
# 从python转成tensor
t = tf.convert_to_tensor(list, dtype=tf.float32)
# 从numpy构建tensor
array = np.array([[1, 2, 3], [4, 5, 6]])
t = tf.convert_to_tensor(array,dtype=tf.float32)
print(t.shape[1]) # 查看维度,[1]为第二个维度即列
# 互转
print(t.numpy()) # tensor转为numpy的ndarray
print(t.numpy().tolist()) # numpy再转为list
修改和判断
t = tf.Variable(tf.zeros(shape=[2, 5], dtype=tf.float32))
# 试图通过赋值的方式修改Tensor里的值,需要使用assign函数,并且Tensor需要是Variable(可修改的)
# t[:,1]所有行的第二列
# 必须用assign()修改
t[:, 1].assign(tf.convert_to_tensor([1, 1], dtype=tf.float32))
mask = t > 0 #逐个判断t的每一个元素是否大于0,mask和t的shape一致
简单运算
# 随机正态分布
A = tf.random.normal(shape=[2, 5])
B = tf.random.normal(shape=[2, 5])
C = A + B # 两个Tensor逐元素相加,下同
C = tf.add(A, B)
D = A * B # 两个Tensor逐元素相乘,下同
D = tf.multiply(A, B)
# transpose:转置
# perm:可随意互换维度
B_T = tf.transpose(B, perm=[1, 0]) # 第1维和第0维互调
E = tf.matmul(A, B_T) # 矩阵乘法
变维
A = tf.random.normal(shape=[2, 5])
B = tf.expand_dims(A, 2) # (2, 5, 1) 扩出第2维,第二维1
print(B.shape)
C = tf.squeeze(B, 2) # (2, 5) 减掉第2维,将是1的维度全部打掉
print(C.shape)
# -1自动填充,reshape中-1只能出现一次
D = tf.reshape(A, shape=[-1, 1, 5])
# 二维变三维,第1维的dim变成1,第2维的dim变成5,自动推断第0维的dim
print(D.shape) # (2, 1, 5)
Layer在末维上执行运算
A = tf.random.normal(shape=[4, 3, 3, 2, 5]) # 五维高阶矩阵
linear = tf.keras.layers.Dense(units=10) # 全连接层中输出层有10个神经元
B = linear(A) # 在最后一维上进行线性变换,前4维不动,即最后一维的5参与运算,5个神经元作为输入
print(B.shape) # (4, 3, 3, 2, 10)
conv = tf.keras.layers.Conv2D(filters=6, kernel_size=[3, 2]) # 输出通道有6个,卷积核大小是[3,2]
C = conv(A) # A的最后3维被视为(图片高度、图片宽度、图片channel个数)。最后3维参与卷积运算,前面的维度保持不变
# A可以看成[3,2,5],kernel_size=[3, 2],最后输出通道为6,所以可以得到[1,1,6],拼接之前的[4,3]
print(C.shape) # (4, 3, 1, 1, 6)。[1,1]是feature_map的大小,6是out channel的个数
维度广播
A = tf.ones(shape=[1, 3])
print(A.shape) # (1, 3)
B = tf.convert_to_tensor([[2.], [2.]]) #[2,1]
print(B.shape) # (2, 1)
C = A + B # 逐位相加。A在第0位上升维,追平B的第0维。B在第1维上进行升维,追平A的第1维。通过复制的方式进行长维
print(C.numpy().tolist()) # [[3.0, 3.0, 3.0], [3.0, 3.0, 3.0]]
深度学习常用操作
Embedding层
离散特征先转化为向量,通过映射
![](https://img.haomeiwen.com/i27579716/b71c18b5a488901c.png)
vocab_szie = 1234
embedding_dim = 10
init_weights = tf.ones(shape=[vocab_szie, embedding_dim])
embed_layer = tf.keras.layers.Embedding(
input_dim=vocab_szie, # Embedding矩阵的行数
output_dim=embedding_dim, # Embedding矩阵的列数
weights=[init_weights], # 使用预先训练好的embedding
trainable=True, # 允许再训练
)
input = tf.convert_to_tensor([3, 5, 0, 8])
output = embed_layer(input)
print(output) # shape=(4, 10),所有元素全是1
离散特征通过Embedding连续化
通常会先使用word2vec初始化右图中的embedding,再根据上层任务对embedding进行调整,这样上层任务能比较快地达到最优解。这其实就是迁移学习的思想。
![](https://img.haomeiwen.com/i27579716/2564a268d95c7286.png)
import fasttext
from sklearn.metrics.pairwise import cosine_similarity
import numpy as np
model = fasttext.train_unsupervised(input="data/title_words.txt",
model='skipgram', #skipgram和cbow
neg=10, # 负样本个数
lr=0.05, # 学习率
dim=100, # 向量维度
ws=5, # 上下文窗口大小
min_count=5, # 过滤低频词
minn=1,
maxn=6, # 最小和最大符长度
word_ngrams=1,
#ngrams>1时会把多个词当一个整体,为它训练一个向量
epoch=100,thread=8)
model.save_model("model/job_word_embed")
model = fasttext.load_model("model/job_word_embed")
v1=model["数据挖掘"]
v2=model["机器学习"]
print("similarity of 数据挖掘 and 机器学习 is %f" % cosine_similarity(np.array([v1, v2]))[0, 1])
BatchNormalization
BatchNormalization的目的在于减轻内部协方差漂移的问题,即特征的分布经常在训练过程中持续变化。
在这种情况下,所需训练的参数就要不断地适应变化的特征分布,从而增大了训练的难度。
批标准化,在第一步对特征进行标准化,来获得一个固定的分布,然后在训练过程中自适应地调整这个分布。
所以BN操作通常有助于加快收敛。
观测时BatchNormalization使用所有训练样本的均值和方差。
![](https://img.haomeiwen.com/i27579716/2c65753fcfa63151.png)
DropOut
dropOut思想跟随机森林如出一辙,在前向计算时随机丢弃一部分神经元,防止特征之间的互相依赖和影响。 具体做法是:
按一定比例rate选取某层上的部分神经元,将其输出置为0,剩下的神经元将其输出扩大到原来的1/(1-rate)倍,这样保持整体的和不变。
![](https://img.haomeiwen.com/i27579716/0b983655f4c8e255.png)
激活函数和损失函数
ReLU激活函数的导数要么是1,要么是0,特征在层间传递的时候,其取值范围大致不变,避免进入S型函数的平坦区域,从而导致梯度消失或梯度爆炸。
分类问题通常用交叉熵损失函数,相比于平方误差,权重的梯度不容易衰减到0。
![](https://img.haomeiwen.com/i27579716/8890ef3065fe9075.png)
构建深度模型
定义
import tensorflow as tf
from tensorflow.keras.layers import Dense, BatchNormalization, Dropout, ReLU from tensorflow.keras.models import Model, Sequential
class DNN(Model): # 自定义Model
def __init__(self):
super(DNN, self).__init__()
self.fc = Sequential([ # 由多个Model串联而成
BatchNormalization(), Dropout(0.5), Dense(units=32), ReLU(), BatchNormalization(), Dropout(0.5), Dense(units=1, activation=tf.nn.sigmoid)
])
# 产生输出
def call(self, inputs, *args, **kwargs):
y = self.fc(inputs)
return y
第一种model训练
from tensorflow.keras.optimizers import Adam
from tensorflow.keras.callbacks import EarlyStopping
model = DNN()
optimizer = Adam(learning_rate=1e-4) # 优化算法
x = tf.ones(shape=[100, 20])
y = tf.ones(shape=[100])
model.compile(loss='categorical_crossentropy', optimizer=optimizer)
# 二分类交叉熵损失函数
early_stop = EarlyStopping(monitor='loss', min_delta=1e-3, patience=2) # 连续patience轮loss变化很小时(小于min_delta),提前停止迭代
model.fit(x, y, batch_size=16, epochs=10, callbacks=[early_stop])
第二种model训练
batch_size = 16
epoch = 10
n = x.shape[0]
for epoch in range(epochs):
step=0
for begin in range(0,n,batch_size):
end = begin +batch_size
if end > n:
end = n
batch_x = x[begin:end]
batch_y = y[begin:end]
with tf.GradientTape() as tape:
y_hat = tf.squeeze(model(batch_x))
loss = tf.nn.sigmoid_cross_entropy_with_logits(batch_y,y_hat)
grads = tape.gradient(loss,model.trainable_variable)
optimizer.apply_gradients(zip(grads,model.trainable_variables))
print(" epoch{} step {} train_loss {}".format(epoch,step,np.mean(loss.numpy()))
step += 1
网友评论