Python PyTorch的TensorFlow等效物';s transforms.Normalize()

Python PyTorch的TensorFlow等效物';s transforms.Normalize(),python,tensorflow,deep-learning,pytorch,tensorflow2.0,Python,Tensorflow,Deep Learning,Pytorch,Tensorflow2.0,我试图推断最初在PyTorch中构建的TFLite模型。我一直遵循的路线,并必须预处理图像沿RGB通道。我发现与transforms.Normalize()最接近的TensorFlow等价物是tf.image.per\u image\u standarization()()。虽然这是一个很好的匹配,tf.image.per_image_standarization()通过跨通道获取平均值和标准差来实现这一点,并将其应用于这些通道。下面是他们从 def per_image_标准化(图像): “”“

我试图推断最初在PyTorch中构建的TFLite模型。我一直遵循的路线,并必须预处理图像沿RGB通道。我发现与
transforms.Normalize()
最接近的TensorFlow等价物是
tf.image.per\u image\u standarization()
()。虽然这是一个很好的匹配,
tf.image.per_image_standarization()
通过跨通道获取平均值和标准差来实现这一点,并将其应用于这些通道。下面是他们从

def per_image_标准化(图像):
“”“线性缩放`image`使其具有零平均值和单位范数。”。
此op计算“(x-平均值)/调整后的标准差”,其中“平均值”是平均值
图像中所有值的
`调整后的_stddev=max(stddev,1.0/sqrt(image.numements())`)。
`stddev`是'image'中所有值的标准偏差。它是有上限的
远离零以防止在处理均匀图像时被0除。
Args:
图像:形状为“[高度、宽度、通道]”的三维张量。
返回:
与“图像”形状相同的标准化图像。
提出:
ValueError:如果“图像”的形状与此函数不兼容。
"""
image=ops.convert_to_tensor(image,name='image')
_检查3DImage(图像,需要\u static=False)
num\u pixels=math\u ops.reduce\u prod(数组\u ops.shape(图像))
image=math_ops.cast(image,dtype=dtypes.float32)
图像平均值=数学运算。减少平均值(图像)
方差=(数学运算减少平均值(数学运算平方(图))-
数学运算平方(图像平均值))
偏差=发电机运行偏差(偏差)
STDEV=数学运算sqrt(方差)
#应用最小规格化,以保护我们不受均匀图像的影响。
min_stddev=math_ops.rsqrt(math_ops.cast(num_pixels,dtypes.float32))
像素值比例=数学运算最大值(标准差,最小标准差)
像素值偏移量=图像平均值
图像=数学运算减去(图像、像素值、偏移)
图像=数学运算div(图像、像素值、比例)
返回图像
而PyTorch的
transforms.Normalize()
允许我们提及每个通道应用的平均值和标准差,如下所示

#转换
pose_transform=transforms.Compose([
transforms.ToTensor(),
归一化(平均值=[0.485,0.456,0.406],
标准=[0.229,0.224,0.225]),
])
在TensorFlow 2.x中获得此功能的方法是什么

编辑: 我创建了一个快速的错误,似乎通过定义这样一个函数来解决这个问题:

def标准化图像(图像、平均值、标准):
对于范围(3)内的通道:
图像[:,:,频道]=(图像[:,:,频道]-平均[频道]/std[频道]
返回图像

我不确定这是否有效,但似乎能完成工作。在输入到模型之前,我仍然需要将输出转换为张量。

您提到的解决方法似乎还可以。但是使用
for…loop
计算单个图像的每个RGB通道的标准化,在处理数据管道中的大型数据集(
generator
tf.data
)时可能会有点问题。但无论如何都没关系。这是您的方法的演示,稍后我们将提供两种可能的替代方案,它们可能很容易为您工作

from PIL import Image 
from matplotlib.pyplot import imshow, subplot, title, hist

# load image (RGB)
img = Image.open('/content/9.jpg')

def normalize_image(image, mean, std):
    for channel in range(3):
        image[:,:,channel] = (image[:,:,channel] - mean[channel]) / std[channel]
    return image

OP_approach = normalize_image(np.array(img) / 255.0, 
                            mean=[0.485, 0.456, 0.406], 
                            std=[0.229, 0.224, 0.225])
现在,让我们在后面观察变换属性

plt.figure(figsize=(25,10))
subplot(121); imshow(OP_approach); title(f'Normalized Image \n min-px: \
    {OP_approach.min()} \n max-pix: {OP_approach.max()}')
subplot(122); hist(OP_approach.ravel(), bins=50, density=True); \ 
                                    title('Histogram - pixel distribution')

标准化后的最小和最大像素范围分别为(
-2.117909301310043
2.639999999997

选择2 我们可以使用预处理层来做同样的事情。它需要两个重要的参数,它们是
平均值
方差
(std的平方)

归一化后的最小和最大像素范围分别为(
-2.0357144
2.64

选择3 这更像是减去平均值
mean
,然后除以平均值
std

from tensorflow.keras.experimental.preprocessing import Normalization

input_data = np.array(img)/255
layer = Normalization(mean=[0.485, 0.456, 0.406], 
                      variance=[np.square(0.299), 
                                np.square(0.224), 
                                np.square(0.225)])

plt.figure(figsize=(25,10))
subplot(121); imshow(layer(input_data).numpy()); title(f'Normalized Image \n min-px: \
   {layer(input_data).numpy().min()} \n max-pix: {layer(input_data).numpy().max()}')
subplot(122); hist(layer(input_data).numpy().ravel(), bins=50, density=True);\
   title('Histogram - pixel distribution')
norm_img = ((tf.cast(np.array(img), tf.float32) / 255.0) - 0.449) / 0.226

plt.figure(figsize=(25,10))
subplot(121); imshow(norm_img.numpy()); title(f'Normalized Image \n min-px: \
{norm_img.numpy().min()} \n max-pix: {norm_img.numpy().max()}')
subplot(122); hist(norm_img.numpy().ravel(), bins=50, density=True); \
title('Histogram - pixel distribution')

归一化后的最小和最大像素范围分别为(
-1.9867257
2.4380531
)。最后,如果我们与
pytorch
方法进行比较,这些方法之间没有太大区别

import torchvision.transforms as transforms

transform_norm = transforms.Compose([
    transforms.ToTensor(),
    transforms.Normalize(mean=[0.485, 0.456, 0.406],
                            std=[0.229, 0.224, 0.225]),
])
norm_pt = transform_norm(img)

plt.figure(figsize=(25,10))
subplot(121); imshow(np.array(norm_pt).transpose(1, 2, 0));\
  title(f'Normalized Image \n min-px: \
  {np.array(norm_pt).min()} \n max-pix: {np.array(norm_pt).max()}')
subplot(122); hist(np.array(norm_pt).ravel(), bins=50, density=True); \
  title('Histogram - pixel distribution')


归一化后的最小和最大像素范围分别为(
-2.117904
2.64
)。

关于
tf.keras.experimental.preprocessing.Normalize()的情况如何。您可以将其添加为顶部的一个层,它将规范化批处理中的所有图像。感谢您的建议,但我不确定如何将单个平均std值应用于相应的rgb值,我得到
TypeError:\uuuu init\uuuu()当我将均值和方差列表传递给函数时,参数“axis”得到了多个值。
错误。你能分享在Keras中使用
归一化
层的代码吗(这导致了前面评论中提到的错误)?谢谢你的回答。在@pavel的注释之后,我将代码更改为keras规范化,在对语法进行了一点修改之后。“我真的很感谢你详细介绍这些细节。”greysou1很高兴这有帮助。别忘了打个招呼