1. NumPy'deki şekillerin anlamı
"Kelimenin tam anlamıyla bir liste ve tüm listenin sadece bir sayı içerdiği liste listesi olduğunu biliyorum" yazıyorsunuz, ama bu biraz düşünmek için yararsız bir yol.
NumPy diziler düşünmek için en iyi yolu, iki parça, bir oluşur ki veri tampon sadece ham elemanlarının bir blok, ve a görünüşüdür veri tamponu yorumlama açıklamaktadır.
Örneğin, 12 tamsayıdan oluşan bir dizi oluşturursak:
>>> a = numpy.arange(12)
>>> a
array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])
Sonra a
böyle bir şey düzenlenmiş bir veri arabelleğinden oluşur:
┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┐
│ 0 │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ 10 │ 11 │
└────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┘
ve verilerin nasıl yorumlanacağını açıklayan bir görünüm:
>>> a.flags
C_CONTIGUOUS : True
F_CONTIGUOUS : True
OWNDATA : True
WRITEABLE : True
ALIGNED : True
UPDATEIFCOPY : False
>>> a.dtype
dtype('int64')
>>> a.itemsize
8
>>> a.strides
(8,)
>>> a.shape
(12,)
Burada şekil (12,)
, dizinin 0'dan 11'e kadar çalışan tek bir dizinle dizine eklendiği anlamına gelir. Kavramsal olarak, bu tek dizini etiketlersek i
dizi a
şöyle görünür:
i= 0 1 2 3 4 5 6 7 8 9 10 11
┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┐
│ 0 │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ 10 │ 11 │
└────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┘
Bir diziyi yeniden şekillendirirsek , veri arabelleği değişmez. Bunun yerine, verileri yorumlamanın farklı bir yolunu tanımlayan yeni bir görünüm oluşturur. Sonra:
>>> b = a.reshape((3, 4))
dizi b
, aynı veri arabelleğine sahiptir a
, ancak şimdi sırasıyla 0'dan 2'ye ve 0'dan 3'e kadar çalışan iki endeksle dizine eklenir . İki dizini etiketlersek i
ve j
dizi şu şekilde b
görünür:
i= 0 0 0 0 1 1 1 1 2 2 2 2
j= 0 1 2 3 0 1 2 3 0 1 2 3
┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┐
│ 0 │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ 10 │ 11 │
└────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┘
bunun anlamı:
>>> b[2,1]
9
İkinci dizinin hızla değiştiğini ve ilk dizinin yavaş değiştiğini görebilirsiniz. Bunun tam tersi olmasını tercih ediyorsanız, order
parametreyi belirtebilirsiniz :
>>> c = a.reshape((3, 4), order='F')
dizine şu şekilde dizin verilir:
i= 0 1 2 0 1 2 0 1 2 0 1 2
j= 0 0 0 1 1 1 2 2 2 3 3 3
┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┐
│ 0 │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ 10 │ 11 │
└────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┘
bunun anlamı:
>>> c[2,1]
5
Şimdi, bir dizinin 1 veya daha fazla boyutu olan bir şekle sahip olmasının ne anlama geldiği açık olmalıdır.
>>> d = a.reshape((12, 1))
dizi d
, birincisi 0'dan 11'e kadar çalışan iki dizin tarafından dizine eklenir ve ikinci dizin her zaman 0'dır:
i= 0 1 2 3 4 5 6 7 8 9 10 11
j= 0 0 0 0 0 0 0 0 0 0 0 0
┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┐
│ 0 │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ 10 │ 11 │
└────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┘
ve bu yüzden:
>>> d[10,0]
10
Uzunluk 1'in boyutu "özgür" (bir anlamda), yani sizi şehre gitmekten alıkoyan bir şey yok:
>>> e = a.reshape((1, 2, 1, 6, 1))
şöyle dizine eklenmiş bir dizi vererek:
i= 0 0 0 0 0 0 0 0 0 0 0 0
j= 0 0 0 0 0 0 1 1 1 1 1 1
k= 0 0 0 0 0 0 0 0 0 0 0 0
l= 0 1 2 3 4 5 0 1 2 3 4 5
m= 0 0 0 0 0 0 0 0 0 0 0 0
┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┐
│ 0 │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ 10 │ 11 │
└────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┘
ve bu yüzden:
>>> e[0,1,0,0,0]
6
Dizilerin nasıl uygulandığı hakkında daha fazla bilgi için NumPy dahili belgelerine bakın .
2. Ne yapmalı?
Yana numpy.reshape
sadece yeni bir görünüm oluşturur, sen gerektiğinde bunu kullanma konusunda korkmak gerekir. Bir diziyi farklı bir şekilde dizine eklemek istediğinizde kullanmak için doğru araçtır.
Bununla birlikte, uzun bir hesaplamada, ilk etapta "doğru" şekle sahip diziler oluşturmak ve böylece yeniden şekillendirme ve aktarım sayısını en aza indirmek genellikle mümkündür. Ancak yeniden şekillendirme ihtiyacına yol açan gerçek bağlamı görmeden neyin değiştirilmesi gerektiğini söylemek zor.
Sorunuzdaki örnek şudur:
numpy.dot(M[:,0], numpy.ones((1, R)))
ama bu gerçekçi değil. İlk olarak, bu ifade:
M[:,0].sum()
sonucu daha basit hesaplar. İkincisi, sütun 0 hakkında gerçekten özel bir şey var mı? Belki de aslında ihtiyacınız olan şey:
M.sum(axis=0)