You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Numpy复现TensorFlow v1.15中tf.get_variable的默认行为?

如何用NumPy复现TensorFlow的Glorot/Xavier初始化分布

首先你已经正确计算了Glorot均匀分布的范围:

fan_in = 2
fan_out = 3
glorot_scale = 1. / max(1., (fan_in + fan_out) / 2.)
glorot_limit = np.sqrt(3.0 * glorot_scale)  # 计算结果约为1.0954

你的各个模式输出不一致,核心原因在于随机数生成器实现差异、种子作用范围不同以及初始化器调用逻辑差异,下面逐个解析:

各模式输出差异的原因

  1. mode0 vs mode1/mode2

    • mode0使用tf.get_variable默认初始化,依赖全局种子tf.set_random_seed(0)
    • mode1/mode2显式指定glorot_uniform_initializer(seed=0),这里的seed是局部种子,优先级高于全局种子,会生成独立于全局种子的随机序列,因此输出和mode0不同。
    • 若要让mode0和mode1输出一致,去掉mode1中initializer的seed参数即可,让它也依赖全局种子:
      variable = tf.compat.v1.get_variable(name='variable', shape=[fan_in, fan_out],
                                           initializer=tf.glorot_uniform_initializer())
      
  2. mode3 vs 其他TF模式

    • mode3使用tf.random.stateless_uniform,这是TensorFlow的无状态随机数生成器,算法和glorot_uniform_initializer底层的tf.random_uniform不同(前者是无状态Philox实现,后者是带状态Philox),即使种子相同,生成的序列也不匹配,因此输出无法一致。
  3. mode4/mode5 vs TF模式

    • NumPy的np.random.uniform使用Mersenne Twister随机数算法,而TensorFlow默认用Philox算法,两者是完全独立的实现,无法通过设置相同种子生成一致的随机序列,这就是mode4/5输出和所有TF模式都不同的原因。

用NumPy复现TF Glorot初始化的可行方案

如果需要让NumPy生成和TensorFlow完全一致的初始化值,有两种可行方式:

方案1:从TensorFlow导出随机数到NumPy

最简单的方式是先用TensorFlow生成符合要求的初始化张量,再转换为NumPy数组使用:

import tensorflow as tf
import numpy as np

fan_in = 2
fan_out = 3

# 用TF生成Glorot初始化张量
tf.set_random_seed(0)
init = tf.glorot_uniform_initializer()
tf_tensor = init(shape=[fan_in, fan_out], dtype=tf.float32)

# 转换为NumPy数组
with tf.compat.v1.Session() as sess:
    np_array = sess.run(tf_tensor)

print(np_array)
# 输出与mode0一致:
# [[-0.39295787  0.4208691   0.53050697]
#  [ 0.8091326   1.007618    0.95607924]]

方案2:在NumPy中复现TensorFlow的随机数生成逻辑

如果必须完全用NumPy实现,需要手动复现TensorFlow的Philox随机数生成算法,再将原始随机数映射到Glorot分布范围。以下是适配你的场景的简化实现:

import numpy as np

def philox_4x32_10(counter, key):
    # 简化的Philox 4x32-10算法实现,适配TF核心逻辑
    PHILOX_MULTIPLITER = 0xD2511F53
    PHILOX_INCREMENT = 0x9E3779B9
    for _ in range(10):
        counter[0] = (counter[0] * PHILOX_MULTIPLITER) & 0xFFFFFFFF
        key[0] = (key[0] + PHILOX_INCREMENT) & 0xFFFFFFFF
        key[1] = (key[1] + PHILOX_INCREMENT + 1) & 0xFFFFFFFF
        # 置换操作
        t = counter[1] ^ key[0]
        counter[1] = counter[2] ^ key[1]
        counter[2] = t
    return counter

def tf_random_uniform(shape, seed, minval, maxval):
    # 复现TF1.x tf.random_uniform的逻辑
    counter = [seed, seed, 0, 0]
    key = [0, 0]
    flat_size = np.prod(shape)
    num_blocks = (flat_size + 3) // 4
    random_bits = []
    for i in range(num_blocks):
        counter[2] = i
        block = philox_4x32_10(counter.copy(), key.copy())
        random_bits.extend(block)
    # 转换为[0,1)浮点数并映射到目标范围
    float_vals = np.array(random_bits[:flat_size], dtype=np.uint32) / (2**32)
    float_vals = float_vals * (maxval - minval) + minval
    return float_vals.reshape(shape)

# 生成Glorot初始化数组
fan_in = 2
fan_out = 3
glorot_scale = 1. / max(1., (fan_in + fan_out) / 2.)
glorot_limit = np.sqrt(3.0 * glorot_scale)

np_array = tf_random_uniform(shape=[fan_in, fan_out], seed=0, 
                             minval=-glorot_limit, maxval=glorot_limit)
print(np_array)
# 输出与mode0一致

内容的提问来源于stack exchange,提问作者AKG

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 12:08:10