您能帮助我理解为什么他们使用- IMAGE_MEAN
和/ IMAGE_STD
吗?
private static final float IMAGE_MEAN = 127.5f; private static final float IMAGE_STD = 127.5f; //...@Override protected void addPixelValue(int pixelValue) { imgData.putFloat((((pixelValue >> 16) & 0xFF) - IMAGE_MEAN) / IMAGE_STD); imgData.putFloat((((pixelValue >> 8) & 0xFF) - IMAGE_MEAN) / IMAGE_STD); imgData.putFloat(((pixelValue & 0xFF) - IMAGE_MEAN) / IMAGE_STD); }
您会注意到,这对于量化示例来说是不必要的(参见https://github.com/tensorflow/examples/blob/master/lite/examples/image_classification/android/app/src/main/java/org/tensorflow/lite/examples/classification/tflite/ClassifierQuantizedMobileNet.java)。
@Override protected void addPixelValue(int pixelValue) { imgData.put((byte) ((pixelValue >> 16) & 0xFF)); imgData.put((byte) ((pixelValue >> 8) & 0xFF)); imgData.put((byte) (pixelValue & 0xFF)); }
目前的粗略想法是….
- 127.5 = 255 / 2。像素通常以0-255的范围表示颜色。这是该范围的正中间。因此,每个像素颜色都被调整到-1到1之间…但为什么呢?
回答:
127.5 = 255 / 2。像素通常以0-255的范围表示颜色。这是该范围的正中间。因此,每个像素颜色都被调整到-1到1之间…
这是完全正确的。
但为什么呢?
输入归一化是机器学习中的常用技术。这个特定的模型是以-1到1的输入值范围训练的,因此我们应该将推理输入归一化到相同的范围以获得最佳结果。
为了提供一些直观理解,如果输入没有归一化到-1到1之间,会出现什么问题:
- 例如,如果我们错误地设置IMAGE_MEAN=0.0f & IMAGE_STD = 255.0f,它会将输入归一化到0到1之间。模型仍然能“看到”图像,但一切都会变得更亮。准确率可能会略有下降
- 如果我们不进行归一化而只是简单地将uint8转换为float,值范围将是0~255,而期望的是-1~1。模型可能会“看到”一个超亮/白色的图像。准确率可能会显著下降或完全不起作用。
范围可以是任意的。-1~1和0~1经常被使用。关键是相同的归一化应该应用于训练和推理。