tf.reverse_sequence()简述

TensorFlow中tf.reverse_sequence()的使用解析
本文简要介绍TensorFlow中的tf.reverse_sequence()函数,该函数用于按指定轴翻转序列,常用于双向LSTM的反向传播。通过示例说明了seq_axis和batch_axis参数的作用,并提供了测试代码展示其功能。
部署运行你感兴趣的模型镜像

tf.reverse_sequence()简述

在看bidirectional_dynamic_rnn()的源码的时候,看到了代码中有调用 reverse_sequence()这一方法,于是又回去看了下这个函数的用法,发现还是有点意思的。根据名字就可以能看得出,这个方法主要是用来翻转序列的,就像双线LSTM中在反向传播那里需要从下文往上文处理一样,需要对序列做一个镜像的翻转处理。

先来看一下这个方法的定义:

reverse_sequence(
    input,
    seq_lengths,
    seq_axis=None,
    batch_axis=None,
    name=None,
    seq_dim=None,
    batch_dim=None)
  • 其中input是输入的需要翻转的目标张量,seq_lengths是一个张量;
  • 其元素是input中每一处需要翻转时翻转的长度,在双向LSTM中这个值统一被设为输入语句的长度,代表着整句话都需要被翻转,而实际上张量中的元素值可以是不同的,下面的例子中就可以看出;
  • seq_axis和seq_dim的关系,在源码中做了如下操作:
seq_axis = deprecation.deprecated_argument_lookup("seq_axis", seq_axis,
                                                    "seq_dim", seq_dim)

返回中return gen_array_ops.reverse_sequence(..., seq_dim=seq_axis,...),同理,对于batch_axis和batch_dim也是相同的处理。意义上来说,按照官方给出的解释,“此操作首先沿着维度batch_axis对input进行分割,并且对于每个切片 i,将前 seq_lengths 元素沿维度 seq_axis 反转”。实际上通俗来理解,就是对于张量input中的第batch_axis维中的每一个子张量,在这个子张量的第seq_axis维上进行翻转,翻转的长度为 seq_lengths 张量中对应的数值。

举个例子,如果 batch_axis=0,seq_axis=1,则代表我希望每一行为单位分开处理,对于每一行中的每一列进行翻转。相反的,如果 batch_axis=1,seq_axis=0,则是以列为单位,对于每一列的张量,进行相应行的翻转。回头去看双向RNN的源码,就可以理解当time_major这一属性不同时,time_dim 和 batch_dim 这一对组合的取值为什么恰好是相反的了。

写一个简单的测试代码:

a = tf.constant([[1,2,3], [4,5,6], [7,8,9]])
l = tf.constant([1,2,3],tf.int64) # 每一次翻转长度分别为1,2,3.由于a是(3,3)维的,所以l中数值最大只能是3
x = tf.reverse_sequence(a,seq_lengths=l,seq_axis = 0,batch_axis= 1) # 以列为单位进行翻转,翻转的是每一行的元素
y = tf.reverse_sequence(a,seq_lengths=l,seq_axis = 1,batch_axis= 0) # 以行为单位进行翻转,翻转的是每一列的元素
with tf.Session() as sess:
    print(sess.run(x))
    print(sess.run(y))

结果如下:

# 每一列上的元素种类没有发生变化,但是从每一行来看,行的顺序分别翻转了前1,前2,前3个元素
[[1 5 9]
 [4 2 6]
 [7 8 3]]
# 每一行上的元素种类没有发生变化,但是从每一列来看,列的顺序分别翻转了前1,前2,前3个元素
[[1 2 3]
 [5 4 6]
 [9 8 7]]

您可能感兴趣的与本文相关的镜像

TensorFlow-v2.15

TensorFlow-v2.15

TensorFlow

TensorFlow 是由Google Brain 团队开发的开源机器学习框架,广泛应用于深度学习研究和生产环境。 它提供了一个灵活的平台,用于构建和训练各种机器学习模型

@tf.function def train_step(inp_SNR, noise, GS_flag, PS_flag, eq_flag, epsilon=1e-12, min_distance_threshold=0.5): loss = 0 with tf.GradientTape() as tape: # 原始前向传播计算 s_logits = logit_model(inp_SNR) # batch_size = tf.shape(inp_SNR)[0] # s_logits = tf.zeros((batch_size, M), dtype=tf.float32) s = s_model(s_logits) soft_bits = soft_bit_encoder(s) hard_bits = hard_decision_on_bit(soft_bits) enc = Trans_model_bit(hard_bits) # 生成完整星座图 bit_set = tf.math.mod(tf.bitwise.right_shift(tf.expand_dims(symbol_set, 1), tf.range(bitlen)), 2) bit_set = tf.reverse(bit_set, axis=[-1]) constellation = Trans_model_bit(bit_set) constellation = tf.expand_dims(constellation, 0) # 归一化处理 p_s = tf.nn.softmax(s_logits) magnitudes = tf.abs(constellation) max_mag = tf.reduce_max(magnitudes) norm_factor = 1.30793 / tf.maximum(max_mag, epsilon) norm_constellation = r2c(norm_factor) * constellation x = r2c(norm_factor) * enc # === 星座点最小距离约束 === points = tf.squeeze(tf.stack([tf.math.real(norm_constellation), tf.math.imag(norm_constellation)], axis=-1)) diff = tf.expand_dims(points, 1) - tf.expand_dims(points, 0) # [M, M, 2] distances = tf.norm(diff, axis=-1) # [M, M] mask = tf.eye(tf.shape(distances)[0], dtype=tf.bool) valid_distances = tf.where(mask, tf.ones_like(distances)*1e10, distances) min_distance = tf.reduce_min(valid_distances) distance_penalty = tf.nn.relu(min_distance_threshold - min_distance) * 50.0 # === 新增:概率分布可逆性约束 === # 1. 计算初始均匀分布的熵(基准值) num_constellation_points = tf.cast(tf.shape(constellation)[1], tf.float32) # 使用换底公式计算log2: log2(x) = ln(x)/ln(2) uniform_entropy = tf.math.log(num_constellation_points) / tf.math.log(2.0) # 均匀分布的熵 # 2. 计算当前分布的熵 current_entropy = -tf.reduce_sum(p_s * tf.math.log(p_s) / tf.math.log(2.0)) # 以2为底的熵 # 3. 熵约束惩罚 entropy_ratio = current_entropy / uniform_entropy entropy_penalty = tf.nn.relu(0.9 - entropy_ratio) * 200.0 # 4. 概率下限约束 min_prob = tf.reduce_min(p_s) prob_floor_penalty = tf.nn.relu(epsilon - min_prob) * 200.0 # === 原始损失计算 === Tx = upsample_pulse_shaping(x, Fs, h_rrc, fa, fc) Rx = Tx + noise y = Model_Eq(Rx) entropy_S = -p_norm(p_s, p_s, lambda x: log2(x)) GMI = GMIcal_tf(x, tf.squeeze(y), M, norm_constellation, hard_bits_out, p_s) NGMI = 1 - (entropy_S - GMI) / bitlen loss_NGMI = tf.nn.relu(NGMI_th - NGMI) loss_Eq = tf.reduce_mean(tf.square(tf.abs(x - y))) # === 修改后的损失函数(添加所有惩罚项) === loss = (loss_Eq * eq_flag * 0.5 - GMI + loss_NGMI * 100 + distance_penalty + entropy_penalty # 新增:熵约束惩罚 + prob_floor_penalty) # 新增:概率下限惩罚 # # 梯度计算与更新 # variables = [] # if PS_flag == 1: # variables.extend(logit_model.trainable_variables) # variables.extend(s_model.trainable_variables) # if GS_flag == 1: # variables.extend(Trans_model_bit.trainable_variables) # if eq_flag == 1: # variables.extend(Model_Eq.trainable_variables) variables = (logit_model.trainable_variables * PS_flag + s_model.trainable_variables + Trans_model_bit.trainable_variables * GS_flag + Model_Eq.trainable_variables * eq_flag) gradients = tape.gradient(loss, variables) optimizer.apply_gradients(zip(gradients, variables)) # 保持原始返回值结构不变 return loss, loss_Eq, NGMI, GMI, tf.reduce_mean(entropy_S), p_s, norm_constellation, x, min_distance 新增约束条件,一个点与其相邻三个点的概率和不能超过4/M。当前代码可以正常运行,修改时只修改必要地方
最新发布
08-22
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值