我有一些简单的代码,可以加载mnist数据并标准化图像。
mnist = tf.keras.datasets.mnist
(x_train, y_train),(x_test, y_test) = mnist.load_data()
x_train = x_train/255.0
x_test = x_test/255.0
上面的代码有效,但是,如果我尝试使用速记除法,则会出现错误:
mnist = tf.keras.datasets.mnist
(x_train, y_train),(x_test, y_test) = mnist.load_data()
x_train /= 255.0
x_test /= 255.0
错误如下:
TypeError: ufunc 'true_divide' output (typecode 'd') could not be coerced to provided output parameter (typecode 'B') according to the casting rule ''same_kind''
通过玩转,我找到了一个解决方案,将x_train
转换为float32
可以消除错误,但是我偶然发现了该修复程序。我不明白为什么下面的代码可以解决问题
mnist = tf.keras.datasets.mnist
(x_train, y_train),(x_test, y_test) = mnist.load_data(path=path)
x_train = x_train.astype('float32')
x_test = x_test.astype('float32')
x_train /= 255.0
x_test /= 255.0
有人可以解释一下这里发生了什么吗?为什么两个版本的行为不同?为什么在第二个实例中需要一个显式的案例,而在第一个实例中却不需要?
我发现在任何地方都记录有这种行为并不太幸运。
编辑:我不确定我需要提供什么其他“调试细节”,因为我基本上已经提供了完整的代码,结果以及我不理解的细节。我也没有收到任何评论来解释为什么关闭该问题和/或期望在此处获得其他信息。我希望进行一些建设性的批评,以便至少可以以一种更好的方式提出这个问题,如果目前的形式本身不能令人满意。
答案 0 :(得分:1)
增强除法(x_train /= 255.
)不仅仅是常规除法的简写。它的实现方式不同于常规划分方式,并且具有不同的意图。
Python对象具有实现算术函数的方法。
/
是__truediv__(self, other): ==> object
/=
是__itruediv__(self, other): ==> object
两者都返回结果对象(请参见 Emulating numeric types(在python文档中)。
它们相似,但是在使用可变对象(例如列表或numpy
数组)时具有不同的意图。 __truediv__
不应修改self
,而__itruediv__
应该修改。实现可以随意忽略,但是通常c = a / b
不应修改a
,而a /= b
应该修改a
。当某个对象未实现__itruediv__
时,python会退回到__truediv__
-不可变对象通常无法实现增强版本,因为它们无法修改自身。
对于numpy数组,增强除法(/=
)最终会调用numpy.true_divide。由于扩充除法修改了原始数组,因此它使用out
参数将结果广播到原始对象中。这就是错误的所在-您不能将不同的数据类型广播到现有数组中。增强分割与
>>> import numpy as np
>>> x_train = np.array([1,2,3], dtype='B')
>>> np.true_divide(x_train, 255., out=x_train)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: ufunc 'true_divide' output (typecode 'd') could not be coerced to provided output parameter (typecode 'B') according to the casting rule ''same_kind''
其中标准划分与
相同>>> x_train = np.array([1,2,3], dtype='B')
>>> foo = np.true_divide(x_train, 255.)
>>> x_train = foo
在您的情况下,部门上的差异并不是真正的错误。由于您的操作创建了不同的类型,因此numpy需要分配不同大小的内存块来容纳它。您可以坚持使用非增强除法,也可以像对float32一样预先转换数组。它们都是合理的方法。增强运算符的窍门是要注意,它们将结果广播回原始数组,并具有广播的所有限制。
答案 1 :(得分:0)
如果您不想将类型更改为float32
,则可以执行以下操作:
mnist = tf.keras.datasets.mnist
(x_train, y_train),(x_test, y_test) = mnist.load_data()
div = x_train / 255.0
x_train = div