1. ホーム
  2. python

Numpyの0d配列はなぜスカラーとみなされないのですか?

2023-12-02 21:28:17

質問

確かに0d配列はスカラーですが、Numpyはそう考えていないようです。何か見落としているのか、それとも私がその概念を誤解しているだけなのでしょうか?

>>> foo = numpy.array(1.11111111111, numpy.float64)
>>> numpy.ndim(foo)
0
>>> numpy.isscalar(foo)
False
>>> foo.item()
1.11111111111

どのように解決するのですか?

あまり難しく考えない方がいい。その方が結局は個人の精神衛生上も寿命的にも良いのです。

Numpyのスカラー型に関する不思議な状況は、1x1行列をスカラー型に劣化させる優雅で一貫した方法がないという事実から産み出されました。数学的には同じものであるにもかかわらず、これらは非常に異なるコードによって処理されます。

もしあなたが科学的なコードを少しでも書いていたなら、最終的には以下のようなものを望むでしょう。 max(a) のようなものが、スカラーであっても、すべてのサイズの行列で動作することを望むでしょう。数学的には、これは完全に理にかなったことです。しかし、プログラマにとっては、Numpy でスカラーを示すものはすべて .shape と .ndim 属性を持つべきであり、少なくとも ufuncs は Numpy の 21 種類のスカラーに対して入力で明示的に型チェックを行う必要がないことを意味しているのです。

一方、既存のPythonのライブラリで で明示的に型チェックを行う既存のPythonライブラリとも連携する必要があります。これはジレンマで、Numpyのndarrayはスカラーになったときに個別に型を変更しなければならず、すべてのアクセスに対してチェックを行わないと、それが発生したかどうか知る方法がありません。実際にそのルートを進むと、スカラー型の基準では、おそらくビット動作がとんでもなく遅くなってしまうでしょう。

Numpy開発者の解決策は、独自のスカラー型のためにndarrayとPythonのスカラーの両方を継承し、すべてのスカラーが.shape、.ndim、.T、などなどを持っているようにすることです。1x1 の行列はまだ存在しますが、スカラーを扱うことが分かっている場合は、その使用は控えるようにします。これは理論的にはうまくいくはずですが、時折、ペイント ローラーで失敗した場所を目にすることがあり、醜い内部がすべての人に見えるように露出していることがあります。

>>> from numpy import *
>>> a = array(1)
>>> b = int_(1)
>>> a.ndim
0
>>> b.ndim
0
>>> a[...]
array(1)
>>> a[()]
1
>>> b[...]
array(1)
>>> b[()]
1

特に理由はないのですが a[...]a[()] は異なるものを返すべきですが、そうなっています。これを変更するための提案がありますが、1x1 配列のための仕事を終えるのを忘れていたようです。

潜在的により大きな、そしておそらく解決不可能な問題は、Numpyのスカラーがイミュータブルであるという事実です。したがって、スカラーを ndarray に噴霧すること、数学的には配列をスカラーに折り畳むことの隣接操作は、実装するのが困難です。Numpyのスカラーを実際に成長させることはできませんし、定義上ndarrayにキャストすることはできませんが、たとえ newaxis は不思議と機能するのですが。

>>> b[0,1,2,3] = 1
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'numpy.int32' object does not support item assignment
>>> b[newaxis]
array([1])

Matlabでは、スカラーのサイズを大きくすることは全く問題なく、頭を使わない操作です。Numpyの場合は、ジャラジャラしたものをくっつける必要があります。 a = array(a) を貼り付けなければならない。 を考える で、スカラーで始まって配列で終わる可能性があります。私はNumpyがPythonとうまくやるためにこのようにしなければならない理由を理解していますが、だからといって、多くの新しいスイッチャーがこのことに深く戸惑っているという事実は変わりません。この挙動に苦労して、最終的に我慢した明確な記憶を持っている人もいれば、あまりに行き過ぎた人は、大抵、最も純真な夢に頻繁につきまとう、深い形のない心の傷が残っています。それは、すべての人にとって醜い状況です。