np.dot
İki 'float32'
2D diziyi aldığımızı varsayalım :
res = np.dot(a, b) # see CASE 1
print(list(res[0])) # list shows more digits
[-0.90448684, -1.1708503, 0.907136, 3.5594249, 1.1374011, -1.3826287]
Sayılar. Dışında değişebilirler:
DURUM 1 : dilima
np.random.seed(1)
a = np.random.randn(9, 6).astype('float32')
b = np.random.randn(6, 6).astype('float32')
for i in range(1, len(a)):
print(list(np.dot(a[:i], b)[0])) # full shape: (i, 6)
[-0.9044868, -1.1708502, 0.90713596, 3.5594249, 1.1374012, -1.3826287]
[-0.90448684, -1.1708503, 0.9071359, 3.5594249, 1.1374011, -1.3826288]
[-0.90448684, -1.1708503, 0.9071359, 3.5594249, 1.1374011, -1.3826288]
[-0.90448684, -1.1708503, 0.907136, 3.5594249, 1.1374011, -1.3826287]
[-0.90448684, -1.1708503, 0.907136, 3.5594249, 1.1374011, -1.3826287]
[-0.90448684, -1.1708503, 0.907136, 3.5594249, 1.1374011, -1.3826287]
[-0.90448684, -1.1708503, 0.907136, 3.5594249, 1.1374011, -1.3826287]
[-0.90448684, -1.1708503, 0.907136, 3.5594249, 1.1374011, -1.3826287]
Yazdırılan dilim aynı sayılarla çarpılmış olsa da sonuçlar farklılık gösterir.
DURUM 2 : düzleştirin
a
, 1D sürümünü alın b
, sonra dilimleyin a
:
np.random.seed(1)
a = np.random.randn(9, 6).astype('float32')
b = np.random.randn(1, 6).astype('float32')
for i in range(1, len(a)):
a_flat = np.expand_dims(a[:i].flatten(), -1) # keep 2D
print(list(np.dot(a_flat, b)[0])) # full shape: (i*6, 6)
[-0.3393164, 0.9528787, 1.3627989, 1.5124314, 0.46389243, 1.437775]
[-0.3393164, 0.9528787, 1.3627989, 1.5124314, 0.46389243, 1.437775]
[-0.3393164, 0.9528787, 1.3627989, 1.5124314, 0.46389243, 1.437775]
[-0.3393164, 0.9528787, 1.3627989, 1.5124314, 0.46389243, 1.437775]
[-0.3393164, 0.9528787, 1.3627989, 1.5124314, 0.46389243, 1.437775]
[-0.3393164, 0.9528787, 1.3627989, 1.5124314, 0.46389243, 1.437775]
[-0.3393164, 0.9528787, 1.3627989, 1.5124314, 0.46389243, 1.437775]
[-0.3393164, 0.9528787, 1.3627989, 1.5124314, 0.46389243, 1.437775]
DURUM 3 : daha güçlü kontrol; dahil olmayan tüm girişleri sıfıra ayarlayın : a[1:] = 0
CASE 1 koduna ekleyin . Sonuç: tutarsızlıklar devam ediyor.
DURUM 4 : dışındaki endeksleri kontrol edin [0]
; gibi [0]
, sonuçlar, sabit bir dizi büyütme sayısını yaratma noktalarından sabitlemeye başlar. Çıktı
np.random.seed(1)
a = np.random.randn(9, 6).astype('float32')
b = np.random.randn(6, 6).astype('float32')
for j in range(len(a) - 2):
for i in range(1, len(a)):
res = np.dot(a[:i], b)
try: print(list(res[j]))
except: pass
print()
Bu nedenle, 2D * 2D durum için sonuçlar farklıdır - ancak 1D * 1D için tutarlıdır. Bazı okumalarımda, bu basit ekleme kullanarak 1D-1D'den kaynaklanıyor gibi görünüyor, oysa 2D-2D daha az hassas olabilen 'meraklı', performansı artıran eklentiyi kullanıyor (örn. Çiftli ekleme bunun tersini yapıyor). Yine de, bir zamanlar a
belirlenmiş bir 'eşiği' aştığında, tutarsızlıkların neden kaybolduğunu anlayamıyorum ; daha büyük a
ve b
daha sonra bu eşik yalan söylüyor gibi görünüyor, ama her zaman var.
Hepsi dedi: np.dot
ND-ND dizileri için neden kesin olmayan (ve tutarsız)? İlgili Git
Ek bilgi :
- Ortam : Win-10 İşletim Sistemi, Python 3.7.4, Spyder 3.3.6 IDE, Anaconda 3.0 2019/10
- İşlemci : i7-7700HQ 2.8 GHz
- Numpy v1.16.5
Olası suçlu kütüphanesi : Numpy MKL - ayrıca BLASS kütüphaneleri; Bi Rico'ya kaydettiği için teşekkürler
Gerilme testi kodu : belirtildiği gibi, daha büyük dizilerle frekanslarda tutarsızlıklar şiddetlenir; eğer yukarıdaki tekrarlanamazsa, aşağıda olmalıdır (eğer değilse, daha büyük loşları deneyin). Çıktı
np.random.seed(1)
a = (0.01*np.random.randn(9, 9999)).astype('float32') # first multiply then type-cast
b = (0.01*np.random.randn(9999, 6)).astype('float32') # *0.01 to bound mults to < 1
for i in range(1, len(a)):
print(list(np.dot(a[:i], b)[0]))
Sorun şiddeti : gösterilen tutarsızlıklar 'küçük', ancak milyarlarca sayının birkaç saniye içinde çarpıldığı ve tüm çalışma süresi boyunca trilyonların bulunduğu bir sinir ağında artık çalışmıyor; bildirilen model doğruluğu, bu iş parçacığı başına yüzde 10'ların tamamından farklıdır .
Aşağıda, temelde a[0]
w / len(a)==1
vs. olan bir modele beslenmeden kaynaklanan diziler bir gif len(a)==32
:
Paul'ün testi sayesinde diğer PLATFORMS sonuçları :
Durum 1 yeniden üretildi (kısmen) :
- Google Colab VM - Intel Xeon 2.3 G-Hz - Jupyter - Python 3.6.8
- Win-10 Pro Docker Masaüstü Bilgisayar - Intel i7-8700K - jupyter / scipy-notebook - Python 3.7.3
- Ubuntu 18.04.2 LTS + Docker - AMD FX-8150 - jupyter / scipy-notebook - Python 3.7.3
Not : bunlar yukarıda gösterilenden çok daha düşük hata verir; ilk satırdaki iki giriş, diğer satırlardaki karşılık gelen girişlerden en az anlamlı basamakta 1 ile kapalıdır.
Durum 1 çoğaltılamadı :
- Ubuntu 18.04.3 LTS - Intel i7-8700K - IPython 5.5.0 - Python 2.7.15+ ve 3.6.8 (2 test)
- Ubuntu 18.04.3 LTS - Intel i5-3320M - IPython 5.5.0 - Python 2.7.15+
- Ubuntu 18.04.2 LTS - AMD FX-8150 - IPython 5.5.0 - Python 2.7.15rc1
Notlar :
- Bağlantılı CoLab dizüstü ve jupyter ortamları sistemimde görülmektedir daha (ve sadece ilk iki sıra için) çok daha az farklılık gösterir. Ayrıca, Durum 2 hiçbir zaman (henüz) kesinsizlik göstermemiştir.
- Bu çok sınırlı örnekte, mevcut (Dockerized) Jupyter ortamı IPython ortamından daha duyarlıdır.
np.show_config()
yayınlamak için çok uzun, ancak özet olarak: IPython envleri BLAS / LAPACK tabanlıdır; Colab OpenBLAS tabanlıdır. IPython Linux envlerinde, BLAS kütüphaneleri sisteme kurulur - Jupyter ve Colab'da / opt / conda / lib'den gelirler
GÜNCELLEME : Kabul edilen cevap doğru, ancak geniş ve eksik. Soru, davranışı kod düzeyinde açıklayabilen herkese açıktır - yani, kullanılan kesin bir algoritma np.dot
ve yukarıdaki sonuçlarda gözlemlenen 'tutarlı tutarsızlıkları' nasıl açıkladı (ayrıca bkz. Yorumlar). İşte benim deşifre ötesinde bazı doğrudan uygulamalar: sdot.c - arraytypes.c.src
ndarrays
genellikle sayısal hassasiyet kaybını göz ardı eder. Çünkü reduce-sum
her eksen boyunca basitlik için , işlemlerin sırası en uygun olmayabilir ... Hassas hatayı düşünürseniz de kullanabilirsinizfloat64