Numpy、TensorFlow和Keras函数输入参数axis理解(二)

本文解析了在使用numpy、TensorFlow及Keras编程时遇到的axis参数的含义与取值范围,通过多个实例展示了如何沿特定轴对张量进行操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在利用numpy、TensorFlow和Keras等进行编程时,经常发现很多函数携带axis参数,且具有相同功能的函数的axis(轴)参数取值范围可能不同(操作方式也不一样),从而引起一些困惑。针对这一问题,归纳总结如下:

2. TensorFlow函数中的axis参数理解

在TensorFlow函数中,axis输入参数的取值范围是[-rank(input_tensor), rank(input_tensor))

2.1 案例1——tf.reduce_sum()

函数原型:

reduce_sum(
input_tensor,
axis=None,
keep_dims=False,
name=None,
reduction_indices=None
)

函数作用:

沿着指定的axis轴,计算输入张量的和

import tensorflow as tf

x = tf.constant([[1, 2, 3], [4, 5, 6]])

sess = tf.InteractiveSession()
print("输入张量:\n",x.eval())

y1 = tf.reduce_sum(x)  
print("所有张量元素的和:\n",y1.eval())

y2 = tf.reduce_sum(x, axis = 0)  
print("沿着张量0轴方向求和:\n",y2.eval())

y3 = tf.reduce_sum(x, axis = 1)  
print("沿着张量1轴方向求和:\n",y3.eval())

y4 = tf.reduce_sum(x, axis = 1, keep_dims=True) 
print("沿着张量1轴方向求和,并保持维度:\n",y4.eval())
输入张量:
 [[1 2 3]
 [4 5 6]]
所有张量元素的和:
 21
沿着张量0轴方向求和:
 [5 7 9]
沿着张量1轴方向求和:
 [ 6 15]
沿着张量1轴方向求和,并保持维度:
 [[ 6]
 [15]]

注意事项:

根据www.tensorflow.org中对tf.reduce_sum()的描述,axis输入参数的取值范围是[-rank(input_tensor), rank(input_tensor)),那么前述的常数张量x(rank = 2,2阶)的axis取值范围是[-2,2),那么axis = -2、-1究竟是什么含义呢?下依旧利用前述所定义的常数张量x进行试验,即

y2 = tf.reduce_sum(x, axis = 0)  
print("沿着张量0轴方向求和:\n",y2.eval())

y5 = tf.reduce_sum(x, axis = -2)  
print("沿着张量-2轴方向求和:\n",y5.eval())

y3 = tf.reduce_sum(x, axis = 1)  
print("沿着张量1轴方向求和:\n",y3.eval())

y6 = tf.reduce_sum(x, axis = -1)  
print("沿着张量-1轴方向求和:\n",y6.eval())
沿着张量0轴方向求和:
 [5 7 9]
沿着张量-2轴方向求和:
 [5 7 9]
沿着张量1轴方向求和:
 [ 6 15]
沿着张量-1轴方向求和:
 [ 6 15]

总结:

根据上述试验发现,在axis = [-2,2)的区间内时,axis的取值虽然可以不同,但是实际的效果却存在相同的情况,即

axis = -2 对应 axis = 0,效果一致;

axis = -1 对应 axis = 1,效果一致;

2.2 案例2——tf.argmax()

函数原型:

argmax(
input,
axis=None,
name=None,
dimension=None,
output_type=tf.int64
)

函数作用:

沿着指定axis轴的方向寻找最大值,并返回对应的索引

import numpy as np
import tensorflow as tf
A = np.random.random((3,4))
x = tf.constant(A)

sess = tf.InteractiveSession()
print("输入张量:\n",x.eval())

y1 = tf.argmax(x) 
print("axis缺省时,默认axis = 0:\n",y1.eval())

y2 = tf.argmax(x, axis = 0)  
print("沿着张量0轴方向求和:\n",y2.eval())

y3 = tf.argmax(x, axis = 1)  
print("沿着张量1轴方向求和:\n",y3.eval())
输入张量:
 [[ 0.34570824  0.4327304   0.81727727  0.01683761]
 [ 0.66160006  0.49774433  0.03712519  0.10179577]
 [ 0.17496762  0.48599597  0.90044948  0.01108119]]
axis缺省时,默认axis = 0:
 [1 1 2 1]
沿着张量0轴方向求和:
 [1 1 2 1]
沿着张量1轴方向求和:
 [2 0 2]

注意事项:

根据www.tensorflow.org中对tf.argmax()的描述,axis输入参数的取值范围是[-rank(input), rank(input)),那么前述的常数张量x(rank = 2,2阶)的axis取值范围是[-2,2),那么axis = -2、-1究竟是什么含义呢?下依旧利用前述所定义的常数张量x进行试验,即

y2 = tf.argmax(x, axis = 0)  
print("沿着张量0轴方向求和:\n",y2.eval())

y4 = tf.argmax(x, axis = -2)  
print("沿着张量-2轴方向求和:\n",y4.eval())

y3 = tf.argmax(x, axis = 1)  
print("沿着张量1轴方向求和:\n",y3.eval())

y5 = tf.argmax(x, axis = -1)  
print("沿着张量-1轴方向求和:\n",y5.eval())
沿着张量0轴方向求和:
 [1 1 2 1]
沿着张量-2轴方向求和:
 [1 1 2 1]
沿着张量1轴方向求和:
 [2 0 2]
沿着张量-1轴方向求和:
 [2 0 2]

总结:

根据上述试验发现,在axis = [-2,2)的区间内时,axis的取值虽然可以不同,但是实际的效果却存在相同的情况,即

axis = -2 对应 axis = 0,效果一致;

axis = -1 对应 axis = 1,效果一致;

2.3 案例3——tf.concat()

函数原型:

concat(
values,
axis,
name=’concat’
)

函数作用:

沿着指定轴(维度)合并张量

import numpy as np
import tensorflow as tf

A = np.ones((2,2))
B = np.zeros((2,2))
x1 = tf.constant(A)
x2 = tf.constant(B)


sess = tf.InteractiveSession()
print("输入张量1:\n",x1.eval())
print("输入张量2:\n",x2.eval())

y1 = tf.concat([x1,x2], axis = 0)  
print("沿着张量0轴方向合并(垂直合并):\n",y1.eval())

y2 = tf.concat([x1,x2], axis = 1)  
print("沿着张量1轴方向合并(水平合并):\n",y2.eval())
输入张量1:
 [[ 1.  1.]
 [ 1.  1.]]
输入张量2:
 [[ 0.  0.]
 [ 0.  0.]]
沿着张量0轴方向合并(垂直合并):
 [[ 1.  1.]
 [ 1.  1.]
 [ 0.  0.]
 [ 0.  0.]]
沿着张量1轴方向合并(水平合并):
 [[ 1.  1.  0.  0.]
 [ 1.  1.  0.  0.]]

注意事项:

根据www.tensorflow.org中对tf.concat()的描述,axis输入参数的取值范围是[-rank(values), rank(values)),那么前述的常数张量x(rank = 2,2阶)的axis取值范围是[-2,2),那么axis = -2、-1究竟是什么含义呢?下依旧利用前述所定义的常数张量x进行试验,即

y1 = tf.concat([x1,x2], axis = 0)  
print("沿着张量0轴方向合并(垂直合并):\n",y1.eval())

y3 = tf.concat([x1,x2], axis = -2)  
print("沿着张量-2轴方向合并(垂直合并):\n",y3.eval())

y2 = tf.concat([x1,x2], axis = 1)  
print("沿着张量1轴方向合并(水平合并):\n",y2.eval())

y4 = tf.concat([x1,x2], axis = -1)  
print("沿着张量-1轴方向合并(水平合并):\n",y4.eval())
沿着张量0轴方向合并(垂直合并):
 [[ 1.  1.]
 [ 1.  1.]
 [ 0.  0.]
 [ 0.  0.]]
沿着张量-2轴方向合并(垂直合并):
 [[ 1.  1.]
 [ 1.  1.]
 [ 0.  0.]
 [ 0.  0.]]
沿着张量1轴方向合并(水平合并):
 [[ 1.  1.  0.  0.]
 [ 1.  1.  0.  0.]]
沿着张量-1轴方向合并(水平合并):
 [[ 1.  1.  0.  0.]
 [ 1.  1.  0.  0.]]

总结:

根据上述试验发现,在axis = [-2,2)的区间内时,axis的取值虽然可以不同,但是实际的效果却存在相同的情况,即

axis = -2 对应 axis = 0,效果一致;

axis = -1 对应 axis = 1,效果一致;

在Tensorflow中还有很多函数中存在axis输入参数,比如tf.reduce_mean()、tf.redunce_max()等函数,其对于的axis理解方式跟上述案例完全一致。

3. Keras函数中的axis参数理解

3.1 案例1——sum()

函数原型:

keras.backend.sum(x, axis=None, keepdims=False)

函数作用:

沿着指定的axis轴,计算张量中值的和

import numpy as np
from keras import backend as K
Using TensorFlow backend.
tf_session = K.get_session()
kcon = K.constant([[1, 2,0], [3, 4,5]])

print("输入张量:\n",kcon.eval())


sum0 = K.sum(kcon,axis = 0) 
print("沿着张量0轴方向求和:\n",sum0.eval())

sum1 = K.sum(kcon,axis = 1) 
print("沿着张量1轴方向求和:\n",sum1.eval())

sum2 = K.sum(kcon) 
print("axis缺省时,所有元素求和:\n",sum2.eval())
输入张量:
 [[ 1.  2.  0.]
 [ 3.  4.  5.]]
沿着张量0轴方向求和:
 [ 4.  6.  5.]
沿着张量1轴方向求和:
 [  3.  12.]
axis缺省时,所有元素求和:
 15.0

注意事项:

在Keras.io中并未明确的介绍axis的取值范围,初步认为应该与TensorFlow一致(因为本程序是基于TensorFlow后端,最底层的运算时基于TensorFlow),实验如下:

sum4 = K.sum(kcon,axis = -2) 
print("沿着张量-2轴方向求和:\n",sum4.eval())

sum5 = K.sum(kcon,axis = -1) 
print("沿着张量-1轴方向求和:\n",sum5.eval())
沿着张量-2轴方向求和:
 [ 4.  6.  5.]
沿着张量-1轴方向求和:
 [  3.  12.]
#下面超过了axis的取值范围[-2,2),因此会报错
sum6 = K.sum(kcon,axis = -3) 
sum7 = K.sum(kcon,axis = -1) 

3.2 案例2——argmax()

函数原型:

keras.bacend.argmax(x, axis=-1)

函数作用:

沿着指定的轴寻找最大值,并返回其索引值

import numpy as np
from keras import backend as K
tf_session = K.get_session()
var = np.random.random((3,5))
kcon = K.constant(var)

print("输入张量:\n",kcon.eval())


y0 = K.argmax(kcon,axis = 0) 
print("沿着张量0轴方向寻找最大值索引:\n",y0.eval())

y1 = K.argmax(kcon,axis = 1) 
print("沿着张量1轴方向寻找最大值索引:\n",y1.eval())

y2 = K.argmax(kcon) 
print("axis缺省时,默认为-1,对应1的结果:\n",y2.eval())
输入张量:
 [[ 0.13900661  0.4054634   0.64765936  0.5716511   0.61112058]
 [ 0.41806924  0.60134852  0.92036146  0.68033886  0.3683911 ]
 [ 0.95494515  0.05807289  0.44499308  0.73589486  0.2641674 ]]
沿着张量0轴方向寻找最大值索引:
 [2 1 1 2 0]
沿着张量1轴方向寻找最大值索引:
 [2 2 0]
axis缺省时,默认为-1,对应1的结果:
 [2 2 0]

4. 结论

根据上述试验表明,无论是Numpy、Tensorflow,还是Keras,如果相关函数中需要输入axis参数,那么axis的取值范围均与输入的秩(阶)有关,axis范围:[-rank(input) ,rank(input)),且虽然axis取值不同,但是最终效果可能与其他的重合,如:

axis = -2 对应 axis = 0,效果一致;

axis = -1 对应 axis = 1,效果一致;

<think>我们正在尝试导入必要的库来构建一个生成对抗网络(GAN)用于生成手写数字。但是,在导入过程中,我们遇到了一个错误。错误信息没有给出,但通常这类错误可能是由于以下几个原因:1.模块名称错误:例如,我们尝试导入的模块或子模块名称不正确。2.版本问题:某些函数或模块在特定版本中可能已被移除或更名。3.安装问题:可能某个库没有正确安装。观察代码中导入的部分:fromtensorflow.keras.layersimportConv2D,Conv2DTranspose在TensorFlow2.x中,`Conv2DTranspose`是存在的,所以这个导入应该是正确的。但是,请注意:在较旧的TensorFlow版本中(比如1.x),我们可能会使用`Conv2DTranspose`,但有时也可能被写作`Deconvolution2D`(不过现在不推荐使用这个名称)。另外,我们导入了`initializers`,但使用方式可能是`initializers.RandomNormal`等。然而,错误发生在这一步,我们需要检查错误信息。由于没有提供具体的错误信息,我们只能猜测。常见的错误可能是:-如果错误是“无法导入Conv2DTranspose”,那么可能是TensorFlow版本过低。在TensorFlow1.4及以上,这个层被引入。但如果你使用的是更早的版本,可能需要升级。但是,考虑到我们使用的是`fromtensorflow.keras.layersimport...`,而TensorFlow2.x已经将Keras整合为`tf.keras`,所以应该没有问题。另一个可能性是拼写错误。检查代码中是否有拼写错误,例如:Conv2DTranspose#正确Conv2DTranspose#注意大小写,Python是大小写敏感的。实际上,`Conv2DTranspose`的拼写是正确的(首字母大写,其余符合驼峰命名)。如果没有拼写错误,那么可能是环境问题。建议的解决方案:1.确保TensorFlow版本在2.0以上。可以通过`pipshowtensorflow`或`print(tf.__version__)`查看。2.如果版本过低,升级TensorFlow:`pipinstall--upgradetensorflow`如果问题仍然存在,可以尝试重新安装TensorFlow。但是,由于问题描述中只说了“这一步出错”,并没有具体的错误信息,我们只能提供一般性的建议。另外,代码中导入了`initializers`,但在后续代码中如何使用?如果后续代码使用了`initializers`,例如:init=initializers.RandomNormal(mean=0.0,stddev=0.02)这是正确的,因为`tf.keras.initializers`中有`RandomNormal`。因此,如果没有具体的错误信息,我们只能建议检查TensorFlow的安装版本。如果错误信息是“Nomodulenamed'tensorflow'”,那么需要安装TensorFlow。现在,假设我们的环境没有问题,我们可以继续构建GAN模型。然而,由于问题要求我们给出代码,并且只能提供Python代码,那么我们将继续写一个GAN的代码,但前提是环境配置正确。以下是一个简单的DCGAN(DeepConvolutionalGAN)用于生成MNIST手写数字的代码。注意,这个代码需要TensorFlow2.x环境。由于我们不知道具体的错误,我们假设导入的问题已经解决(例如,通过升级TensorFlow或修正拼写错误)。代码结构:1.定义生成器模型2.定义判别器模型3.组合GAN模型4.训练过程注意:由于训练GAN需要较长时间,我们只写一个框架,并设置较少的epoch作为示例。如果运行这个代码时出现导入错误,请先确保TensorFlow已正确安装,并且版本至少为2.0。我们开始写代码:</think>在导入TensorFlow相关模块时出错,通常是由以下原因导致: ### 常见原因及解决方案: 1. **TensorFlow未安装或版本不匹配** - 解决方案:安装或更新TensorFlow ```python # 安装最新版TensorFlow !pip install --upgrade tensorflow # 或者安装包含GPU支持的版本 !pip install tensorflow-gpu ``` 2. **模块导入路径错误** - 确保使用正确的导入路径: ```python # 正确导入方式 (TensorFlow 2.x) from tensorflow.keras.layers import Conv2DTranspose # 注意大小写 ``` 3. **环境配置问题** - 创建干净的虚拟环境: ```bash python -m venv tf_env source tf_env/bin/activate # Linux/Mac tf_env\Scripts\activate # Windows pip install tensorflow ``` 4. **CUDA/cuDNN不兼容(GPU版本)** - 检查兼容性:[TensorFlow GPU支持表](https://www.tensorflow.org/install/source#gpu) ### 完整可运行的DCGAN示例代码: ```python import tensorflow as tf from tensorflow.keras import layers, Model, Sequential import numpy as np import matplotlib.pyplot as plt # 1. 数据准备 (X_train, _), (_, _) = tf.keras.datasets.mnist.load_data() X_train = X_train.reshape(-1, 28, 28, 1).astype('float32') X_train = (X_train - 127.5) / 127.5 # 归一化到[-1, 1] BUFFER_SIZE = 60000 BATCH_SIZE = 256 train_dataset = tf.data.Dataset.from_tensor_slices(X_train).shuffle(BUFFER_SIZE).batch(BATCH_SIZE) # 2. 生成器模型 def build_generator(): model = Sequential([ layers.Dense(7*7*256, use_bias=False, input_shape=(100,)), layers.BatchNormalization(), layers.LeakyReLU(0.2), layers.Reshape((7, 7, 256)), layers.Conv2DTranspose(128, (5,5), strides=(1,1), padding='same', use_bias=False), layers.BatchNormalization(), layers.LeakyReLU(0.2), layers.Conv2DTranspose(64, (5,5), strides=(2,2), padding='same', use_bias=False), layers.BatchNormalization(), layers.LeakyReLU(0.2), layers.Conv2DTranspose(1, (5,5), strides=(2,2), padding='same', use_bias=False, activation='tanh') ]) return model # 3. 判别器模型 def build_discriminator(): model = Sequential([ layers.Conv2D(64, (5,5), strides=(2,2), padding='same', input_shape=(28,28,1)), layers.LeakyReLU(0.2), layers.Dropout(0.3), layers.Conv2D(128, (5,5), strides=(2,2), padding='same'), layers.LeakyReLU(0.2), layers.Dropout(0.3), layers.Flatten(), layers.Dense(1) ]) return model # 4. 训练设置 generator = build_generator() discriminator = build_discriminator() cross_entropy = tf.keras.losses.BinaryCrossentropy(from_logits=True) def generator_loss(fake_output): return cross_entropy(tf.ones_like(fake_output), fake_output) def discriminator_loss(real_output, fake_output): real_loss = cross_entropy(tf.ones_like(real_output), real_output) fake_loss = cross_entropy(tf.zeros_like(fake_output), fake_output) return real_loss + fake_loss generator_optimizer = tf.keras.optimizers.Adam(1e-4) discriminator_optimizer = tf.keras.optimizers.Adam(1e-4) # 5. 训练循环 EPOCHS = 50 noise_dim = 100 num_examples_to_generate = 16 seed = tf.random.normal([num_examples_to_generate, noise_dim]) @tf.function def train_step(images): noise = tf.random.normal([BATCH_SIZE, noise_dim]) with tf.GradientTape() as gen_tape, tf.GradientTape() as disc_tape: generated_images = generator(noise, training=True) real_output = discriminator(images, training=True) fake_output = discriminator(generated_images, training=True) gen_loss = generator_loss(fake_output) disc_loss = discriminator_loss(real_output, fake_output) gradients_of_generator = gen_tape.gradient(gen_loss, generator.trainable_variables) gradients_of_discriminator = disc_tape.gradient(disc_loss, discriminator.trainable_variables) generator_optimizer.apply_gradients(zip(gradients_of_generator, generator.trainable_variables)) discriminator_optimizer.apply_gradients(zip(gradients_of_discriminator, discriminator.trainable_variables)) return gen_loss, disc_loss def generate_and_save_images(model, epoch, test_input): predictions = model(test_input, training=False) fig = plt.figure(figsize=(4,4)) for i in range(predictions.shape[0]): plt.subplot(4, 4, i+1) plt.imshow(predictions[i, :, :, 0] * 127.5 + 127.5, cmap='gray') plt.axis('off') plt.savefig(f'image_at_epoch_{epoch:04d}.png') plt.show() # 6. 开始训练 for epoch in range(EPOCHS): for image_batch in train_dataset: gen_loss, disc_loss = train_step(image_batch) # 每5个epoch生成示例图像 if (epoch + 1) % 5 == 0: generate_and_save_images(generator, epoch + 1, seed) print(f'Epoch {epoch+1}/{EPOCHS}, Gen Loss: {gen_loss:.4f}, Disc Loss: {disc_loss:.4f}') # 保存最终模型 generator.save('mnist_generator.h5') ``` ### 关键说明: 1. **Conv2DTranspose**:用于生成器的上采样操作,替代传统的转置卷积 2. **LeakyReLU**:防止梯度消失,特别适合GAN架构 3. **BatchNormalization**:稳定训练过程,加速收敛 4. **Adam优化器**:自适应学习率,适合对抗训练 如果仍有导入错误,请检查: - TensorFlow版本:`print(tf.__version__)` - GPU是否可用:`tf.config.list_physical_devices('GPU')` - 是否在虚拟环境中运行
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值