[英]TensorFlow equivalent of PyTorch's transforms.Normalize()
我正在嘗試推斷最初在 PyTorch 中構建的 TFLite model。 我一直遵循PyTorch 實現的思路,並且必須沿 RGB 通道預處理圖像。 我發現與transforms.Normalize()
最接近的 TensorFlow 是tf.image.per_image_standardization()
( 文檔)。 盡管這是一個很好的匹配, tf.image.per_image_standardization()
通過在通道中獲取均值和標准並將其應用於它們來做到這一點。 這是他們從這里開始的完整實現
def per_image_standardization(image):
"""Linearly scales `image` to have zero mean and unit norm.
This op computes `(x - mean) / adjusted_stddev`, where `mean` is the average
of all values in image, and
`adjusted_stddev = max(stddev, 1.0/sqrt(image.NumElements()))`.
`stddev` is the standard deviation of all values in `image`. It is capped
away from zero to protect against division by 0 when handling uniform images.
Args:
image: 3-D tensor of shape `[height, width, channels]`.
Returns:
The standardized image with same shape as `image`.
Raises:
ValueError: if the shape of 'image' is incompatible with this function.
"""
image = ops.convert_to_tensor(image, name='image')
_Check3DImage(image, require_static=False)
num_pixels = math_ops.reduce_prod(array_ops.shape(image))
image = math_ops.cast(image, dtype=dtypes.float32)
image_mean = math_ops.reduce_mean(image)
variance = (math_ops.reduce_mean(math_ops.square(image)) -
math_ops.square(image_mean))
variance = gen_nn_ops.relu(variance)
stddev = math_ops.sqrt(variance)
# Apply a minimum normalization that protects us against uniform images.
min_stddev = math_ops.rsqrt(math_ops.cast(num_pixels, dtypes.float32))
pixel_value_scale = math_ops.maximum(stddev, min_stddev)
pixel_value_offset = image_mean
image = math_ops.subtract(image, pixel_value_offset)
image = math_ops.div(image, pixel_value_scale)
return image
而 PyTorch 的transforms.Normalize()
允許我們提及要在每個通道中應用的平均值和標准差,如下所示。
# transformation
pose_transform = transforms.Compose([
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406],
std=[0.229, 0.224, 0.225]),
])
在 TensorFlow 2.x 中獲得此功能的方法是什么?
編輯:我創建了一個快速的 botch,似乎通過定義 function 來解決這個問題:
def normalize_image(image, mean, std):
for channel in range(3):
image[:,:,channel] = (image[:,:,channel] - mean[channel])/std[channel]
return image
我不確定這有多有效,但似乎可以完成工作。 在輸入到 model 之前,我仍然需要將 output 轉換為張量。
您提到的解決方法似乎沒問題。 但是,當您處理數據管道( generator
或tf.data
)中的大型數據集時,使用for...loop
計算單個圖像的每個 RGB通道的歸一化可能會有點問題。 但無論如何沒關系。 這是您的方法的演示,稍后我們將提供兩種可能的替代方案,它們可能很容易為您工作。
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.1179039301310043
, 2.6399999999999997
)。
我們可以使用tf. keras...歸一化預處理層做同樣的事情。 它需要兩個重要的 arguments ,它們是mean
和variance
( 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')
歸一化后的最小和最大像素2.64
分別為( -2.0357144
)。
這更像是減去平均mean
並除以平均std
。
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')
歸一化后的最小和最大像素2.4380531
-1.9867257
。 最后,如果我們與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.64
分別為( -2.117904
)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.