Tensorflow入门

作者: Nefelibatas | 来源:发表于2022-02-12 09:17 被阅读0次
image-20220210231616076.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层

离散特征先转化为向量,通过映射

image-20220210234645310.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进行调整,这样上层任务能比较快地达到最优解。这其实就是迁移学习的思想。

image-20220210234716606.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使用所有训练样本的均值和方差。

image-20220211000008148.png

DropOut

dropOut思想跟随机森林如出一辙,在前向计算时随机丢弃一部分神经元,防止特征之间的互相依赖和影响。 具体做法是:

按一定比例rate选取某层上的部分神经元,将其输出置为0,剩下的神经元将其输出扩大到原来的1/(1-rate)倍,这样保持整体的和不变。

image-20220211000033791.png

激活函数和损失函数

ReLU激活函数的导数要么是1,要么是0,特征在层间传递的时候,其取值范围大致不变,避免进入S型函数的平坦区域,从而导致梯度消失或梯度爆炸。

ReLU(x)= \begin{cases} x& \text{if x>0}\\ 0& \text{else} \end{cases}

分类问题通常用交叉熵损失函数,相比于平方误差,权重的梯度不容易衰减到0。

image-20220211000807117.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

相关文章

网友评论

    本文标题:Tensorflow入门

    本文链接:https://www.haomeiwen.com/subject/btjtlrtx.html