源码tensorflow1.13转化2.0出现问题未解决,求解答

import tensorflow.compat.v1 as tf
#import tensorflow as tf
import numpy as np
#from tensorflow.contrib import rnn
from tensorflow.python.ops import rnn,rnn_cell
#from tensorflow.contrib.crf import crf_log_likelihood #crf_log_likehood条件随机场的对数似然
from tensorflow_addons.text.crf import crf_log_likelihood
import inspect
#from tensorflow.python.keras.optimizers import adam_v2
from tensorflow.python.keras.optimizers import Adam
tf.disable_v2_behavior()
from tensorflow import keras
#from tensorflow.keras import layers
#x=layers.Flatten()


# In[2]:


def network(inputs,shapes,num_tags,lstm_dim=100,initializer=tf.compat.v1.truncated_normal_initializer()):
    #接收一个批次样本的特征数据,计算出网络输出值
    #:param char:2-D[None,None]第一个是批次,第二个是长度,填充的长度
    #:param bound:2-D[None,None]
    #:param flag:2-D[None,None]
    #:param radical:2-D[None,None]
    #:param pinyin:2-D[None,None]
    
    #-----------------------------------特征嵌入(embedding_lookup)————将所有特征id转换成一个固定长度的向量---------------------
    
    embedding=[]
    keys=list(shapes.keys())
    for key in keys:
        #下面转化为循环语句代替
        with tf.variable_scope(key+'_embedding'):#定义一个变量空间
            lookup=tf.get_variable(
                name=key+'_embedding',
                shape=shapes[key],
                initializer=initializer#初始化
            )
            embedding.append(tf.nn.embedding_lookup(lookup, inputs[key]))#对inputs里的char等进行映射,分别将char等特征映射成char_lookup的向量 
    embed=tf.concat(embedding,axis=-1)#最后一个维度上进行特征拼接 #shape [None,None,char_dim+bound_dim+flag_dim+radical_dim+pinyin_dim]
    
    
    sign=tf.sign(tf.abs(inputs[keys[0]]))#将不是0都变为1,最终将每一行求和变为句子真实长度 tf.sign将负数变为-1,0变为0,正数变为1  tf.abs()求数值的绝对值
    lengths=tf.reduce_sum(sign,reduction_indices=1)#reduce_sum去掉所有长度为1,若char第一个批次为1,怕两个将都去掉,因此指定reduction_indices=1
    #最终求出句子的真实长度
    num_time=tf.shape(inputs[keys[0]])[1]#获取序列的长度(包括填充的长度)
    
    
    
    
#-------------------------循环神经网络编码---------------------------------------
    with tf.variable_scope('BiLstm_layer1'):#定义第一层的BILSTM
        lstm_cell={}#应该有两个cell
        for name in['forward1','backward1']:#第一层的前向与后向
            with tf.variable_scope(name):                
                lstm_cell[name]=tf.nn.rnn_cell.BasicLSTMCell(
                    #状态向量的维度是个稳定的数值,需要定义lstm_dim进行传递(默认100)
                    lstm_dim,#神经元的个数
                )
        outputs1,finial_states1=tf.nn.bidirectional_dynamic_rnn(
            lstm_cell['forward1'],
            lstm_cell['backward1'],
            embed,
            dtype=tf.float32,
            sequence_length=lengths#将每个句子的实际长度告知,(由于前文的进行句子填充,减少计算)
        )#bidirectional_dynamic_rnn为双向动态rnn
    outputs1=tf.concat(outputs1,axis=-1)#b,L,2*LSTM_DIM
    
    
    with tf.variable_scope('BiLstm_layer2'):#定义第二层的BILSTM
        lstm_cell={}#应该有两个cell
        for name in['forward','backward']:#第二层的前向与后向
            with tf.variable_scope(name):
                lstm_cell[name]=tf.nn.rnn_cell.BasicLSTMCell(
                    #状态向量的维度是个稳定的数值,需要定义lstm_dim进行传递(默认100)
                    lstm_dim#神经元的个数  
                 )
        outputs,finial_statesl=tf.nn.bidirectional_dynamic_rnn(
            lstm_cell['forward'],
            lstm_cell['backward'],
            outputs1,
            dtype=tf.float32,
            sequence_length=lengths#将每个句子的实际长度告知,(由于前文的进行句子填充,减少计算)
        ) #bidirectional_dynamic_rnn为双向动态rnn
    output=tf.concat(outputs,axis=-1)#batch_size,max_length,2*lstm_dim



#----------------------------------------输出映射------------------矩阵相乘-------两个全连接
    output=tf.reshape(output,[-1,2*lstm_dim])#reshape成二维矩阵 batch_size*maxlength,2*lstm_dim
    with tf.variable_scope('project_layer1'):
        w=tf.get_variable(
            name='w',
            shape=[2*lstm_dim,lstm_dim],
            initializer=initializer        
        )
        b=tf.get_variable(
            name='b',
            shape=[lstm_dim],
            initializer=tf.zeros_initializer()
        
        )
        output=tf.nn.relu(tf.matmul(output,w)+b)#tf.nn.relu为激活函数
    with tf.variable_scope('project_layer2'):
        w=tf.get_variable(
            name='w',
            shape=[lstm_dim,num_tags],
            initializer=initializer        
        )
        b=tf.get_variable(
            name='b',
            shape=[num_tags],
            initializer=tf.zeros_initializer()
        
        )
        output=tf.matmul(output,w)+b
    output=tf.reshape(output,[-1,num_time,num_tags])   
    
    return output,lengths #batch_size,max_length,num_tags  lengths
    #最终将序列的输出和每一句话的真实长度都返回给我
    
    


# In[3]:


class Model(object):   
    def __init__(self,dict,lr=0.0001):
        #------------用到的参数值---------------
        self.num_char=len(dict['word'][0])#具体有多少个字
        self.num_bound=len(dict['bound'][0])
        self.num_flag=len(dict['flag'][0])
        self.num_radical=len(dict['radical'][0])
        self.num_pinyin=len(dict['pinyin'][0])
        self.num_tags=len(dict['label'][0])
        self.char_dim=100#字符要映射成多少的向量,即每个字的特征
        self.bound_dim=20#每个边界特征
        self.flag_dim=50#每个字标签特征
        self.radical_dim=50#每个偏旁特征
        self.pinyin_dim=50#每个拼音特征
        self.lstm_dim=100
        self.lr=lr
        
        
        #---------------------定义接收数据的placeholder--------------------------
        tf.compat.v1.disable_eager_execution()
        # 修改前--x = tf.placeholder(dtype=tf.int32,shape=[None,None],name='number')
        # 修改后--x = tf.Variable(tf.zeros(shape=[None,None]),name='number')
        #self.char_inputs=tf.Variable(tf.zeros(shape=[None,None]),name='char_inputs')
        self.char_inputs=tf.placeholder(dtype=tf.int32,shape=[None,None],name='char_inputs')
        #self.bound_inputs=tf.Variable(tf.zeros(shape=[None,None]),name='bound_inputs')
        self.bound_inputs=tf.placeholder(dtype=tf.int32,shape=[None,None],name='bound_inputs')
        #self.flag_inputs=tf.Variable(tf.zeros(shape=[None,None]),name='flag_inputs')
        self.flag_inputs=tf.placeholder(dtype=tf.int32,shape=[None,None],name='flag_inputs')
        #self.radical_inputs=tf.Variable(tf.zeros(shape=[None,None]),name='radical_inputs')
        self.radical_inputs=tf.placeholder(dtype=tf.int32,shape=[None,None],name='radical_inputs')
        #self.pinyin_inputs=tf.Variable(tf.zeros(shape=[None,None]),name='pinyin_inputs')
        self.pinyin_inputs=tf.placeholder(dtype=tf.int32,shape=[None,None],name='pinyin_inputs')
        #self.targets=tf.Variable(tf.zeros(shape=[None,None]),name='targets')
        self.targets=tf.placeholder(dtype=tf.int32,shape=[None,None],name='targets')#target为真实值
        
        self.global_step=tf.Variable(0,trainable=False)
        #global_step记录的是当前训练的迭代次数 trainable的作用就是决定该层在训练时是否更新权重。当为True时则更新,为False时不更新
        #无需更新,只用来计数
        
        
        
        #---------------------计算模型输出值---------------------------
        self.logits,self.lengths=self.get_logits(self.char_inputs,
                                                 self.bound_inputs,
                                                 self.flag_inputs,
                                                 self.radical_inputs,
                                                 self.pinyin_inputs
                                                )
        
        
        
        
        #----------------------计算损失--------------------------------
        self.cost=self.loss(self.logits,self.targets,self.lengths)
        
        
        
        #----------------------优化器优化---------------------------(如果后期损失值过大,考虑梯度是否过大)
        #采用梯度截断技术
        #tf.variable_scope用于定义创建变量(层)的操作的上下文管理器。
  
        #with tf.variable_scope('optimizer'):
            #opt=adam_v2.Adam(self.lr)
            #opt=tf.keras.optimizers.Adam(self.lr)
            #opt=tf.train.AdamOptimizer(self.lr)
            #grad_vars=opt.compute_gradients(self.cost)
            #计算出所有参数的导数
            #clip_grad_vars=[[tf.clip_by_value(g,-5,5),v] for g,v in grad_vars]
            #按照值进行截断,g、v通过限定值进行截断
            #clip_grad_vars为截断之后的梯度
            #self.train_op=opt.apply_gradients(clip_grad_vars,self.global_step)
            #使用截断后的梯度,进行参数的更新 即clip_grad_vars每次更新,后续计数加一
        #self.saver=tf.Train.Saver(tf.global_variables(),max_to_keep=5)#模型保存器   max_to_keep=5只保留5次最新的模型,如果硬盘足够大,可以大一些
        with tf.variable_scope('optimizer'):
            #opt=adam_v2.Adam(self.lr)
            opt=Adam(self.lr)
            with tf.GradientTape() as tape:
                grads=tape.gradient(self.cost,tf.trainable_variables())
            clip_grad_vars = [[tf.clip_by_value(g, -5, 5), v] for g, v in zip(grads, dict)]
            # 使用截断后的梯度,进行参数的更新,即clip_grad_vars每次更新,后续计数加1
            self.train_op = opt.apply_gradients(clip_grad_vars, self.global_step)
        self.saver = tf.train.Saver(tf.global_variables(), max_to_keep=5)
            
            
            
        
        
    def get_logits(self,char,bound,flag,radical,pinyin):#定义一个网络,接受一个批次样本的特征数据,计算一个网络的输出值。即x-f(x),不计算损失
        #即为输出
        #char形状是2D[None,None],第一个是批次,第二个是数据长度
        #bound-2D
        #flag-2D
        #radicial-2D
        #pinyin-2D
        #return:3-D[batch_size,max_length,num_tags]    
        shapes={}
        shapes['char']=[self.num_char,self.char_dim]
        shapes['bound']=[self.num_bound,self.bound_dim]
        shapes['flag']=[self.num_flag,self.flag_dim]
        shapes['radical']=[self.num_radical,self.radical_dim]
        shapes['pinyin']=[self.num_pinyin,self.pinyin_dim]
        inputs={}
        inputs['char']=char
        inputs['bound']=bound
        inputs['flag']=flag
        inputs['radical']=radical
        inputs['pinyin']=pinyin
        
        
        return network(inputs,shapes,lstm_dim=self.lstm_dim,num_tags=self.num_tags)
    
    
    
    #------------------定义损失函数---------------------
    def loss(self,output,targets,lengths):#需要接受bilstm输出,真实的标签和真实的句子长度
        b=tf.shape(lengths)[0]
        num_steps=tf.shape(output)[1]#num_steps即加一个时刻
        
        with tf.variable_scope('crf_loss'):#转移矩阵
            small=-1000.0#即概率接近0
            start_logits=tf.concat(
                [small*tf.ones(shape=[b,1,self.num_tags]),tf.zeros(shape=[b,1,1])],axis=-1           
            )#shape=[b,1,self.num_tags]为-1000,最后第32个即tf.zeros(shape=[b,1,1])为0
            pad_logits=tf.cast(small*tf.ones([b,num_steps,1]),tf.float32)#pad_logits每个时刻加一个状态
            
            logits=tf.concat([output,pad_logits],axis=-1)
            logits=tf.concat([start_logits,logits],axis=1)
            targets=tf.concat(
                [tf.cast(self.num_tags*tf.ones([b,1]),tf.int32),targets],axis=-1           
            )
            
            self.trans=tf.get_variable(
                name='trans',
                shape=[self.num_tags+1,self.num_tags+1],
                initializer=tf.truncated_normal_initializer()
            )#self.trans转移矩阵体现关系
            
            log_likehood,self.trans=crf_log_likelihood(
                inputs=logits,
                tag_indices=targets,
                transition_params=self.trans,
                sequence_lengths=lengths
            )
            return tf.reduce_mean(-log_likehood)#log_likehood最大化,但是为了降维最小化,加负号
            
        


# In[4]:


#bilstm进行特征提取,CRF相较于传统的CRF++的统计算法,整个序列作归一化,将200维向量映射为31维向量

grads=tape.gradient(self.cost,tf.trainable_variables())这一句报错,求解答

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值