2

如果字段包含floats. 但是,即使我一个接一个地遍历每个字段,我也会收到警告。

for idt, dt in enumerate(data.dtype.names):
    if "float32" in data.dtype[idt].name:
        stds = np.std(data[dt])
        means = np.mean(data[dt])
        data[dt] = (data[dt] - means) / stds

执行最后一行后会弹出:

FutureWarning:Numpy 检测到您(可能正在)写入由 numpy.diagonal 返回的数组或通过选择结构化数组中的多个字段。此代码可能会在未来的 numpy 版本中中断 - 有关详细信息,请参阅 numpy.diagonal 或 arrays.indexing 参考文档。快速解决方法是进行显式复制(例如,执行 arr.diagonal().copy() 或 arr[['f0','f1']].copy())。data[dt] = (data[dt] - 表示) / stds

我可以在调试器中逐行运行它,以确保一切都符合预期,例如:

In[]: data.dtype
Out[]: dtype([('a', '<f4'), ('b', '<f4'), ('c', '<f4'), ('d', '<i4')])
In[]: dt
Out[]: 'a'
In[]: data[dt].shape
Out[]: (2000, 8)

按照警告消息中的建议,复制数组有效:

data2 = data.copy()
for idt, dt in enumerate(data2.dtype.names):
    if "float32" in data2.dtype[idt].name:
        stds = np.std(data2[dt])
        means = np.mean(data2[dt])
        data2[dt] = (data2[dt] - means) / stds
data = data2

摆脱警告的更优雅的方法是什么?在这种情况下,副本发生了什么变化?

4

1 回答 1

1
def foo(data):
    for idt, dt in enumerate(data.dtype.names):
        if "float32" in data.dtype[idt].name:
            data[dt] = data[dt] + idt

In [23]: dt = np.dtype([('a', '<f4'), ('b', '<f4'), ('c', '<f4'), ('d', '<i4')])
In [24]: data = np.ones((3,), dtype=dt)
In [25]: foo(data)
In [26]: data
Out[26]: 
array([( 1.,  2.,  3., 1), ( 1.,  2.,  3., 1), ( 1.,  2.,  3., 1)],
      dtype=[('a', '<f4'), ('b', '<f4'), ('c', '<f4'), ('d', '<i4')])

这可以在没有警告的情况下工作。但是,如果它尝试使用多字段数据选择,我会收到警告:

In [27]: data1 = data[['a','d']]
In [28]: foo(data1)
/usr/local/bin/ipython3:4: FutureWarning: Numpy has detected that you (may be) writing to an array returned
by numpy.diagonal or by selecting multiple fields in a structured
array. This code will likely break in a future numpy release --
see numpy.diagonal or arrays.indexing reference docs for details.
The quick fix is to make an explicit copy (e.g., do
arr.diagonal().copy() or arr[['f0','f1']].copy()).
  import re

对副本进行操作是可以的:

In [38]: data1 = data[['d','a']].copy()
In [39]: foo(data1)
In [40]: data1
Out[40]: 
array([(1,  2.), (1,  2.), (1,  2.)],
      dtype=[('d', '<i4'), ('a', '<f4')])

(接下来我将尝试保存和检索这个数组,h5py看看是否有什么不同。)

h5py,

d1 = f['data']
foo(d1)    # operate directly on the dataset
data1 = d1[:]; foo(data1)    # operate on a copy
data1 = d1[:,'a','b']          # also a copy

我无法使用h5py数据集重现警告。

也可以抑制警告。但首先您需要清楚地了解警告的含义和任何后果。

于 2017-11-30T18:27:15.277 回答