Earth Engine'da oluşturduğunuz algoritmalar, Google bulutunda çalışır ve birçok bilgisayara dağıtılır. Hatalar istemci tarafındaki kodda veya kodlanmış talimatların sunucu tarafında yürütülmesinde ortaya çıkabileceğinden ve hem ölçeklendirme sorunlarından hem de söz dizimi veya mantık hatalarından kaynaklanabileceğinden hata ayıklama zor olabilir. İstemediğiniz sürece programın bulutta çalışan parçaları incelenemez. Bu dokümanda, sık karşılaşılan hataları gidermenize ve Earth Engine komut dosyalarında hata ayıklamanıza yardımcı olacak hata ayıklama stratejileri, araçları ve çözümleri sunulmaktadır.
Söz dizimi hataları
Söz dizimi hataları, kodunuz programlama dilinin kurallarını (Earth Engine'da JavaScript veya Python) ihlal ettiğinde ortaya çıkar. Bu hatalar, kodunuzun çalışmasını engeller ve genellikle yürütmeden önce yakalanır. Söz dizimi hatasıyla karşılaşırsanız vurgulanan satırı veya hata mesajını dikkatlice inceleyin ve Python Dil Referansı veya Google JavaScript Stil Kılavuzu gibi kaynaklara bakın. Kod temizleyiciler de bu sorunları tespit edip düzeltmenize yardımcı olabilir.
İstemci tarafı hataları
Söz dizimi açısından doğru kod olmasına rağmen komut dosyasının tutarlılığı veya mantığıyla ilgili hatalar olabilir. Aşağıdaki örneklerde, var olmayan bir değişkenin ve yöntemin kullanılmasından kaynaklanan hatalar gösterilmektedir.
Hata: Bu kod çalışmıyor.
Kod Düzenleyici (JavaScript)
// Load a Sentinel-2 image. var image = ee.Image('USGS/SRTMGL1_003'); // Error: "bandNames" is not defined in this scope. var display = image.visualize({bands: bandNames, min: 0, max: 9000}); // Error: image.selfAnalyze is not a function var silly = image.selfAnalyze();
import ee import geemap.core as geemap
Colab (Python)
# Load a Sentinel-2 image. image = ee.Image('USGS/SRTMGL1_003') # NameError: name 'band_names' is not defined. display = image.visualize(bands=band_names, min=0, max=9000) # AttributeError: 'Image' object has no attribute 'selfAnalyze'. silly = image.selfAnalyze()
İlk hata, bandNames
değişkeninin atıfta bulunulduğu kapsamda tanımlanmadığını bildirir. Çözüm olarak, değişkeni ayarlayın veya bands
parametresi için bir liste bağımsız değişkeni sağlayın. İkinci hata, var olmayan selfAnalyze()
işlevi çağrıldığında ne olacağını gösterir. Bu, resimlerde gerçek bir yöntem olmadığından hata, bunun bir işlev olmadığını belirtir. Her iki durumda da hata, sorunu açıklayıcı niteliktedir.
Bilinmeyen nesne türü dönüştürme
"...is not a function
" hatası, Earth Engine'ın bir değişkenin türünü bilmemesinden kaynaklanabilir. Bu sorunun yaygın belirtileri şunlardır:
first()
tarafından döndürülen bir nesneyle ilgili bir işlem yapma (koleksiyondaki öğelerin türü bilinmiyor).get()
tarafından döndürülen bir nesneyle ilgili bir işlem yapma (bir mülkte depolanan öğenin türü bilinmiyor).- Bağımsız değişkenin türü bilinmediği halde işlev bağımsız değişkeninde (işlevde) bir işlem yapma
İlkine örnek olarak şunları verebiliriz:
Hata: Bu kod çalışmıyor.
Kod Düzenleyici (JavaScript)
var collection = ee.FeatureCollection('USDOS/LSIB_SIMPLE/2017'); // Error: collection.first(...).area is not a function var area = collection.first().area();
import ee import geemap.core as geemap
Colab (Python)
collection = ee.FeatureCollection('USDOS/LSIB_SIMPLE/2017') # AttributeError: 'Element' object has no attribute 'area'. area = collection.first().area()
Tüm durumlarda çözüm, bilinmeyen türdeki nesneyi bilinen türün kurucusuyla yayınlamaktır. Önceki örneğe devam edersek çözüm, ee.Feature
'e yayınlamaktır:
Çözüm: Yayın cihazı kullanın.
Kod Düzenleyici (JavaScript)
var area = ee.Feature(collection.first()).area();
import ee import geemap.core as geemap
Colab (Python)
area = ee.Feature(collection.first()).area()
(Earth Engine'ın Element
olarak düşündüğü için burada Element
üzerinde herhangi bir yöntemi güvenle çağırabileceğinizi belirtmek isteriz).
İstemci ve sunucu işlevlerini karıştırmayın
Aşağıdaki örnekte ise bu durum daha az belirgindir:
Hata: Bu kod istediğiniz işlemi yapmıyor
Kod Düzenleyici (JavaScript)
// Don't mix EE objects and JavaScript objects. var image = ee.Image('USGS/SRTMGL1_003'); var nonsense = image + 2; // You can print this, but it's not what you were hoping for. print(nonsense); // Error: g.eeObject.name is not a function Map.addLayer(nonsense);
import ee import geemap.core as geemap
Colab (Python)
# Don't mix EE objects and Python objects. image = ee.Image('USGS/SRTMGL1_003') nonsense = image + 2 # TypeError: unsupported operand type(s) for +: 'Image' and 'int'. display(nonsense) # TypeError: unsupported operand type(s) for +: 'Image' and 'int'. m = geemap.Map() m.add_layer(nonsense) m
Bu kodun yazarının, resimdeki her piksele 2
eklemek istediğini varsayalım. Bu, bunu yapmanın doğru yolu değildir. Daha açık belirtmek gerekirse bu kod, sunucu taraflı bir nesneyi (image
) istemci taraflı bir operatörle (+
) yanlış bir şekilde karıştırır. Sonuçlar şaşırtıcı olabilir. İlk durumda, JavaScript Kod Düzenleyici'de nonsense
yazdırıldığında, hem image
hem de 2
dizelere dönüştürülerek ve ardından birleştirilerek istenen işlem (+
) gerçekleştirilir. Elde edilen dize istenmeyen bir dizedir (Python'da TypeError atılır).
İkinci durumda, haritaya nonsense
eklendiğinde, haritaya eklenen nesne (nonsense
) bir EE nesnesi değil, bir dize olduğundan JavaScript Kod Düzenleyici'de anlaşılması zor g.eeObject.name is not a function
hatası görüntülenir (Python'da TypeError atılır). İstenmeyen sonuçları ve bilgilendirici olmayan hataları önlemek için sunucu nesnelerini ve işlevlerini istemci nesneleri, primitifler veya işlevlerle karıştırmayın. Bu örnekte, sunucu işlevi kullanmak çözümdür.
Çözüm: Sunucu işlevi kullanın.
Kod Düzenleyici (JavaScript)
Map.addLayer(image.add(2));
import ee import geemap.core as geemap
Colab (Python)
m = geemap.Map() m.add_layer(image.add(2)) m
Daha fazla bilgi için İstemci ve sunucu sayfasına bakın.
JavaScript Kod Düzenleyici tarayıcı kilidi
Tarayıcı, istemcide JavaScript'in çalışması çok uzun sürdüğünde veya Earth Engine'dan bir şey beklenirken donabilir ya da kilitlenebilir. Bu hatanın en yaygın iki kaynağı, JavaScript Code Editor kodunuzdaki for döngüleri ve/veya getInfo()
'dir. En kötü durum senaryosu ise for döngüsü içinde getInfo()
olmasıdır. For döngüleri, kod makinenizde çalıştığı için tarayıcının kilitlenmesine neden olabilir. Öte yandan,
getInfo()
bir hesaplamanın sonucunu Earth Engine'dan senkronize olarak ister ve sonuç alınana kadar engelleme yapar. Hesaplama uzun sürerse engelleme, tarayıcınızın kilitlenmesine yol açabilir. Kod Düzenleyici'de çalışırken hem for döngülerinden hem de getInfo()
while ifadelerinden kaçının. Daha fazla bilgi için İstemci ve sunucu sayfasına bakın.
Sunucu tarafı hataları
İstemci kodunda mantıksal tutarlılık olmasına rağmen, yalnızca sunucudaki çalışma zamanında ortaya çıkan hatalar olabilir. Aşağıdaki örnekte, var olmayan bir bant elde etmeye çalışırken ne olduğu gösterilmektedir.
Hata: Bu kod çalışmıyor.
Kod Düzenleyici (JavaScript)
// Load a Sentinel-2 image. var s2image = ee.Image( 'COPERNICUS/S2_HARMONIZED/20160625T100617_20160625T170310_T33UVR'); // Error: Image.select: Pattern 'nonBand' did not match any bands. print(s2image.select(['nonBand']));
import ee import geemap.core as geemap
Colab (Python)
# Load a Sentinel-2 image. s2image = ee.Image( 'COPERNICUS/S2_HARMONIZED/20160625T100617_20160625T170310_T33UVR' ) # EEException: Image.select: Band pattern 'non_band' did not match any bands. print(s2image.select(['non_band']).getInfo())
Bu örnekte hata, nonBand
adlı bir bant olmadığını bildirir. Bunun için en bariz çözüm, mevcut bir grup adı belirtmektir. Resmi yazdırıp konsolda inceleyerek veya image.bandNames()
tarafından döndürülen grup adlarının listesini yazdırarak grup adlarını öğrenebilirsiniz.
Değişmezlik
Earth Engine'da oluşturduğunuz sunucu tarafı nesneler immutable. (Her ee.Object
, sunucu tarafı bir Object
'dır). Yani, nesnede değişiklik yapmak isterseniz değişen durumu yeni bir değişkene kaydetmeniz gerekir. Örneğin, Sentinel-2 resminde bir özellik ayarlamak için aşağıdaki yöntem işe yaramaz:
Hata: Bu kod istediğiniz işlemi yapmıyor.
Kod Düzenleyici (JavaScript)
var s2image = ee.Image( 'COPERNICUS/S2_HARMONIZED/20160625T100617_20160625T170310_T33UVR'); s2image.set('myProperty', 'This image is not assigned to a variable'); // This will not result in an error, but will not find 'myProperty'. print(s2image.get('myProperty')); // null
import ee import geemap.core as geemap
Colab (Python)
s2image = ee.Image( 'COPERNICUS/S2_HARMONIZED/20160625T100617_20160625T170310_T33UVR' ) s2image.set('my_property', 'This image is not assigned to a variable') # This will not result in an error, but will not find 'my_property'. display(s2image.get('my_property')) # None
Bu örnekte s2image.set()
, resmin yeni mülkle birlikte bir kopyasını döndürür ancak s2image
değişkeninde depolanan resimde değişiklik olmaz. s2image.set()
tarafından döndürülen resmi yeni bir değişkene kaydetmeniz gerekir. Örneğin:
Çözüm: Sonucu bir değişkende yakalayabilirsiniz.
Kod Düzenleyici (JavaScript)
s2image = s2image.set('myProperty', 'OK'); print(s2image.get('myProperty')); // OK
import ee import geemap.core as geemap
Colab (Python)
s2image = s2image.set('my_property', 'OK') display(s2image.get('my_property')) # OK
Eşlenen işlevler
İstemci ve sunucu işlevlerinin birlikte kullanılamadığı bir diğer bağlam da eşlenen işlevlerdir. Daha açık belirtmek gerekirse, eşlenen işlev tarafından belirtilen işlemler bulutta yürütülür. Bu nedenle, getInfo
ve Export
gibi istemci işlevleri (ve JavaScript Kod Düzenleyici'deki Map
ve Chart
üzerinde print
ve yöntem) eşlenen işlevlerde çalışmaz. Örneğin:
Hata: Bu kod çalışmıyor.
Kod Düzenleyici (JavaScript)
var collection = ee.ImageCollection('MODIS/006/MOD44B'); // Error: A mapped function's arguments cannot be used in client-side operations var badMap3 = collection.map(function(image) { print(image); return image; });
import ee import geemap.core as geemap
Colab (Python)
collection = ee.ImageCollection('MODIS/006/MOD44B') # Error: A mapped function's arguments cannot be used in client-side operations. bad_map_3 = collection.map(lambda image: print(image.getInfo()))
Earth Engine'ın bu kodu Google sunucularında çalıştırılabilir bir talimat dizisine dönüştürmek için kullandığı işlemden kaynaklanan bu hata biraz gizemlidir. İstemci tarafı işlevler ve denetim yapıları, eşlenen işleve iletilen bağımsız değişken resmi üzerinde işlem yapmak için kullanılamaz. Bu hatayı önlemek için eşlenen işlevlerde istemci tarafı işlevler kullanmaktan kaçının. İstemci ve sunucu işlevleri arasındaki fark hakkında daha fazla bilgi edinmek için İstemci ve sunucu sayfasına bakın.
Eşlenen işlevler için ek koşullar vardır. Örneğin, eşlenen işlevler bir değer döndürmelidir:
Hata: Bu kod çalışmıyor.
Kod Düzenleyici (JavaScript)
var collection = ee.ImageCollection('MODIS/006/MOD44B'); // Error: User-defined methods must return a value. var badMap1 = collection.map(function(image) { // Do nothing. });
import ee import geemap.core as geemap
Colab (Python)
collection = ee.ImageCollection('MODIS/006/MOD44B') # Error: User-defined methods must return a value. bad_map_1 = collection.map(lambda image: None)
Bunun çözümü, ürünü iade etmek olabilir. Ancak her tür öğeyi döndüremez. Özellikle, ImageCollection
veya FeatureCollection
üzerinde eşlenen işlevler Image
veya Feature
döndürmelidir. Örneğin, ImageCollection
ile eşlenen bir işlevden tarih döndüremezsiniz:
Hata: Bu kod çalışmıyor.
Kod Düzenleyici (JavaScript)
var collection = ee.ImageCollection('MODIS/006/MOD44B'); var badMap2 = collection.map(function(image) { return image.date(); }); // Error: Collection.map: A mapped algorithm must return a Feature or Image. print(badMap2);
import ee import geemap.core as geemap
Colab (Python)
collection = ee.ImageCollection('MODIS/006/MOD44B') bad_map_2 = collection.map(lambda image: image.date()) # EEException: Collection.map: # A mapped algorithm must return a Feature or Image. print(bad_map_2.getInfo())
Bunu önlemek için giriş resmini yeni bir özellik kümesiyle döndürün. Ardından, koleksiyondaki resimlerin tarihlerinin listesine ihtiyacınız varsa aggregate_array()
ifadesini kullanabilirsiniz:
Çözüm: Mülk ayarlayın.
Kod Düzenleyici (JavaScript)
var collection = ee.ImageCollection('MODIS/006/MOD44B'); var okMap2 = collection.map(function(image) { return image.set('date', image.date()); }); print(okMap2); // Get a list of the dates. var datesList = okMap2.aggregate_array('date'); print(datesList);
import ee import geemap.core as geemap
Colab (Python)
collection = ee.ImageCollection('MODIS/006/MOD44B') ok_map_2 = collection.map(lambda image: image.set('date', image.date())) print(ok_map_2.getInfo()) # Get a list of the dates. dates_list = ok_map_2.aggregate_array('date') print(dates_list.getInfo())
Prosedür hataları
Desen, bant içermeyen bir resme uygulandı
"Pattern 'my_band' was applied to an Image with no bands"
hatası, boş bir bant listesi olan bir resim için ee.Image.select()
çağrısı yapıldığı anlamına gelir. Bu sorunu gidermek için şunları yapabilirsiniz:
- Resim, bir azaltıcı içeren bir ImageCollection'dan veya
first()
ya datoBands()
çağrıları kullanılarak üretiliyorsa kaynak koleksiyonun boş olmadığından emin olun. - Resim,
ee.Dictionary().toImage()
kullanılarak bir sözlükten oluşturuluyorsa sözlüğün boş olmadığından emin olun. - Resim bağımsızsa veri içerdiğinden (yalnızca
ee.Image(0)
olmadığından) emin olun.
Ölçeklendirme hataları
Bir komut dosyası söz dizimsel olarak doğru, mantıksal hata içermiyor ve sunucu için geçerli bir talimat grubunu temsil ediyor olsa da hesaplamanın paralelleştirilmesi ve yürütülmesi sonucunda ortaya çıkan nesneler çok büyük, çok sayıda olabilir veya hesaplamanın yapılması çok uzun sürebilir. Bu durumda, algoritmanın ölçeklendirilemediğini belirten bir hata alırsınız. Bu hatalar genellikle teşhis edilmesi ve çözülmesi en zor olanlardır. Bu tür hatalara örnek olarak aşağıdakiler verilebilir:
- Hesaplama zaman aşımına uğradı
- Çok fazla eşzamanlı toplama
- Kullanıcı bellek sınırı aşıldı
- Bir dahili hata oluştu
Kodunuzun ölçeklendirmesini iyileştirmek, sonuçları daha hızlı almanıza olanak tanır ve tüm kullanıcılar için bilgi işlem kaynaklarının kullanılabilirliğini artırır. Her tür hata, her ölçeklendirme hatasına neden olabilmesiyle kötü bir üne sahip olan ve yaygın olarak kullanılan reduceRegion()
işlevi hakkında kısa bir açıklamanın ardından aşağıdaki bölümlerde ele alınmaktadır.
reduceRegion()
reduceRegion()
, heyecan verici bir dizi hatayı tetikleyecek kadar pikseli açgözlü bir şekilde tüketse de hataları aşmanıza olanak tanıyan, hesaplamayı kontrol etmeyi amaçlayan parametreler de vardır. Örneğin, aşağıdaki önerilmeyen azaltmayı düşünün:
Hata: Bu kod çalışmıyor.
Kod Düzenleyici (JavaScript)
var absurdComputation = ee.Image(1).reduceRegion({ reducer: 'count', geometry: ee.Geometry.Rectangle([-180, -90, 180, 90], null, false), scale: 100, }); // Error: Image.reduceRegion: Too many pixels in the region. // Found 80300348117, but only 10000000 allowed. print(absurdComputation);
import ee import geemap.core as geemap
Colab (Python)
absurd_computation = ee.Image(1).reduceRegion( reducer='count', geometry=ee.Geometry.Rectangle([-180, -90, 180, 90], None, False), scale=100, ) # EEException: Image.reduceRegion: Too many pixels in the region. # Found 80300348117, but only 10000000 allowed. print(absurd_computation.getInfo())
Bu saçma örnek yalnızca gösterim amaçlıdır. Bu hatanın amacı, 80300348117 (80 milyar) pikseli gerçekten azaltmak isteyip istemediğinizi sormaktır. Aksi takdirde, scale
'ü (metre cinsinden piksel boyutu) buna göre artırın veya daha büyük bir ölçeği otomatik olarak yeniden hesaplamak için bestEffort
'ü true olarak ayarlayın. Bu parametrelerle ilgili daha fazla bilgi için reduceRegion()
sayfasına bakın.
Hesaplama zaman aşımına uğradı
Hesabınızda bu piksellerin tümüne ihtiyacınız olduğunu varsayalım. Bu durumda, hesaplamanın başarılı olması için maxPixels
parametresini artırabilirsiniz. Ancak Earth Engine'ın hesaplamayı tamamlaması biraz zaman alacaktır. Sonuç olarak, "hesaplama zaman aşımına uğradı" hatası oluşabilir:
Kötü: Bu tür içerikler paylaşmayın.
Kod Düzenleyici (JavaScript)
var ridiculousComputation = ee.Image(1).reduceRegion({ reducer: 'count', geometry: ee.Geometry.Rectangle([-180, -90, 180, 90], null, false), scale: 100, maxPixels: 1e11 }); // Error: Computation timed out. print(ridiculousComputation);
import ee import geemap.core as geemap
Colab (Python)
ridiculous_computation = ee.Image(1).reduceRegion( reducer='count', geometry=ee.Geometry.Rectangle([-180, -90, 180, 90], None, False), scale=100, maxPixels=int(1e11), ) # Error: Computation timed out. print(ridiculous_computation.getInfo())
Bu hata, Earth Engine'ın hesaplamayı durdurmadan önce yaklaşık beş dakika beklediği anlamına gelir. Dışa aktarma, Earth Engine'ın hesaplamayı daha uzun izin verilen çalışma sürelerine sahip bir ortamda gerçekleştirmesine olanak tanır (ancak daha fazla bellek kullanmaz). reduceRegion()
işlevinin döndürdüğü değer bir sözlük olduğundan, boş geometriye sahip bir özelliğin özelliklerini ayarlamak için sözlüğü kullanabilirsiniz:
İyi. Export
kullanabilirsiniz.
Kod Düzenleyici (JavaScript)
Export.table.toDrive({ collection: ee.FeatureCollection([ ee.Feature(null, ridiculousComputation) ]), description: 'ridiculousComputation', fileFormat: 'CSV' });
import ee import geemap.core as geemap
Colab (Python)
task = ee.batch.Export.table.toDrive( collection=ee.FeatureCollection([ee.Feature(None, ridiculous_computation)]), description='ridiculous_computation', fileFormat='CSV', ) # task.start()
Çok fazla eşzamanlı toplama
Bu hatanın "toplamalar" kısmı, birden fazla makineye yayılmış işlemleri (birden fazla karoyu kapsayan azaltmalar gibi) ifade eder. Earth Engine, bu tür çok fazla toplama işleminin aynı anda çalıştırılmasını önlemek için sınırlar uygular. Bu örnekte, "Çok fazla eşzamanlı toplama" hatası bir haritadaki bir azaltma nedeniyle tetikleniyor:
Kötü: Bu tür içerikler paylaşmayın.
Kod Düzenleyici (JavaScript)
var collection = ee.ImageCollection('LANDSAT/LT05/C02/T1') .filterBounds(ee.Geometry.Point([-123, 43])); var terribleAggregations = collection.map(function(image) { return image.set(image.reduceRegion({ reducer: 'mean', geometry: image.geometry(), scale: 30, maxPixels: 1e9 })); }); // Error: Quota exceeded: Too many concurrent aggregations. print(terribleAggregations);
import ee import geemap.core as geemap
Colab (Python)
collection = ee.ImageCollection('LANDSAT/LT05/C02/T1').filterBounds( ee.Geometry.Point([-123, 43]) ) def apply_mean_aggregation(image): return image.set( image.reduceRegion( reducer='mean', geometry=image.geometry(), scale=30, maxPixels=int(1e9), ) ) terrible_aggregations = collection.map(apply_mean_aggregation) # EEException: Computation timed out. print(terrible_aggregations.getInfo())
Bu kodun amacının her bir resim için resim istatistikleri elde etmek olduğunu varsayarsak olası çözümlerden biri sonucu Export
olarak ayarlamaktır. Örneğin, bir ImageCollection
'ün aynı zamanda FeatureCollection
olduğunu kullanarak resimlerle ilişkili meta veriler tablo olarak dışa aktarılabilir:
İyi. Export
kullanabilirsiniz.
Kod Düzenleyici (JavaScript)
Export.table.toDrive({ collection: terribleAggregations, description: 'terribleAggregations', fileFormat: 'CSV' });
import ee import geemap.core as geemap
Colab (Python)
task = ee.batch.Export.table.toDrive( collection=terrible_aggregations, description='terrible_aggregations', fileFormat='CSV', ) # task.start()
Kullanıcı bellek sınırı aşıldı
Algoritmalarınızın Earth Engine'da paralelleştirilmesinin bir yolu, girişleri karolara bölmek, aynı hesaplamayı her karoda ayrı ayrı çalıştırmak ve ardından sonuçları birleştirmektir. Sonuç olarak, bir çıkış karosunu hesaplamak için gerekli tüm girişlerin belleğe sığması gerekir. Örneğin, giriş çok bantlı bir resim olduğunda, hesaplamada tüm bantlar kullanılırsa çok fazla bellek kullanılmış olabilir. Bu örnekte, bir resim koleksiyonunun tamamını (gereksiz yere) bir karoya zorlamak suretiyle çok fazla bellek kullanıldığı gösterilmektedir:
Kötü: Bu tür içerikler paylaşmayın.
Kod Düzenleyici (JavaScript)
var bands = ['B1', 'B2', 'B3', 'B4', 'B5', 'B6', 'B7']; var memoryHog = ee.ImageCollection('LANDSAT/LT05/C02/T1').select(bands) .toArray() .arrayReduce(ee.Reducer.mean(), [0]) .arrayProject([1]) .arrayFlatten([bands]) .reduceRegion({ reducer: 'mean', geometry: ee.Geometry.Point([-122.27, 37.87]).buffer(1000), scale: 1, bestEffort: true, }); // Error: User memory limit exceeded. print(memoryHog);
import ee import geemap.core as geemap
Colab (Python)
bands = ['B1', 'B2', 'B3', 'B4', 'B5', 'B6', 'B7'] memory_hog = ( ee.ImageCollection('LANDSAT/LT05/C02/T1') .select(bands) .toArray() .arrayReduce(ee.Reducer.mean(), [0]) .arrayProject([1]) .arrayFlatten([bands]) .reduceRegion( reducer=ee.Reducer.mean(), geometry=ee.Geometry.Point([-122.27, 37.87]).buffer(1000), scale=1, bestEffort=True, ) ) # EEException: User memory limit exceeded. print(memory_hog.getInfo())
Bu çok kötü kod, gerçekten ihtiyacınız olmadığı sürece dizi kullanmamanın nedenlerinden birini göstermektedir (Ayrıca "Türü gereksiz yere dönüştürmekten kaçının" bölümüne bakın). Bu koleksiyon dev bir diziye dönüştürüldüğünde, dizinin bir kerede belleğe yüklenmesi gerekir. Uzun bir zaman serisi olduğundan dizi büyüktür ve belleğe sığmaz.
Olası çözümlerden biri, tileScale
parametresini daha yüksek bir değere ayarlamaktır. Daha yüksek tileScale değerleri, karoların tileScale^2
faktörü kadar daha küçük olmasına neden olur. Örneğin, aşağıdakiler hesaplamanın başarılı olmasına olanak tanır:
Kod Düzenleyici (JavaScript)
var bands = ['B1', 'B2', 'B3', 'B4', 'B5', 'B6', 'B7']; var smallerHog = ee.ImageCollection('LANDSAT/LT05/C02/T1').select(bands) .toArray() .arrayReduce(ee.Reducer.mean(), [0]) .arrayProject([1]) .arrayFlatten([bands]) .reduceRegion({ reducer: 'mean', geometry: ee.Geometry.Point([-122.27, 37.87]).buffer(1000), scale: 1, bestEffort: true, tileScale: 16 }); print(smallerHog);
import ee import geemap.core as geemap
Colab (Python)
bands = ['B1', 'B2', 'B3', 'B4', 'B5', 'B6', 'B7'] smaller_hog = ( ee.ImageCollection('LANDSAT/LT05/C02/T1') .select(bands) .toArray() .arrayReduce(ee.Reducer.mean(), [0]) .arrayProject([1]) .arrayFlatten([bands]) .reduceRegion( reducer=ee.Reducer.mean(), geometry=ee.Geometry.Point([-122.27, 37.87]).buffer(1000), scale=1, bestEffort=True, tileScale=16, ) ) print(smaller_hog.getInfo())
Ancak en çok tercih edilen çözüm, dizileri gereksiz yere kullanmamaktır. Böylece tileScale
ile hiç uğraşmanız gerekmez:
İyi: Dizilerden kaçının.
Kod Düzenleyici (JavaScript)
var bands = ['B1', 'B2', 'B3', 'B4', 'B5', 'B6', 'B7']; var okMemory = ee.ImageCollection('LANDSAT/LT05/C02/T1').select(bands) .mean() .reduceRegion({ reducer: 'mean', geometry: ee.Geometry.Point([-122.27, 37.87]).buffer(1000), scale: 1, bestEffort: true, }); print(okMemory);
import ee import geemap.core as geemap
Colab (Python)
bands = ['B1', 'B2', 'B3', 'B4', 'B5', 'B6', 'B7'] ok_memory = ( ee.ImageCollection('LANDSAT/LT05/C02/T1') .select(bands) .mean() .reduceRegion( reducer=ee.Reducer.mean(), geometry=ee.Geometry.Point([-122.27, 37.87]).buffer(1000), scale=1, bestEffort=True, ) ) print(ok_memory.getInfo())
Bir bellek hatasını çözmek için gerekli olmadığı sürece tileScale
değerini ayarlamamalısınız. Çünkü daha küçük karolar da paralelleştirme yükü artırır.
Dahili hatalar
Aşağıdaki gibi bir hatayla karşılaşabilirsiniz:
Bu hatayı alırsanız JavaScript Kod Düzenleyici konsolunda görünen "Hatayı bildir" bağlantısını tıklayın. Yardım düğmesinden de Geri bildirim gönder'i tıklayarak geri bildirim gönderebilirsiniz. Bu hata, komut dosyanızda yalnızca çalışma zamanında ortaya çıkan mantıksal hatalardan veya Earth Engine'ın işleyişiyle ilgili bir sorundan kaynaklanabilir. Her iki durumda da hata bilgilendirici değildir ve düzeltilebilmesi için bildirilmelidir.
Dahili hatalar, aşağıdaki gibi bir request
kimliği içerir:
Bu dizeler, Earth Engine ekibinin belirli sorunları tespit etmesine yardımcı olan benzersiz tanımlayıcılar olarak işlev görür. Bu dizeyi hata raporlarına ekleyin.
Hata ayıklama yöntemleri
Analizinizi kodlayıp çalıştırdığınızda hata aldınız. Şimdi önemli olan nedir? Bu bölümde, sorunu tespit edip düzeltmek için genel hata ayıklama teknikleri açıklanmaktadır.
Değişkenleri ve harita katmanlarını inceleme
Hata veren çok karmaşık bir analiziniz olduğunu varsayalım. Hatanın kaynağı net değilse iyi bir başlangıç stratejisi, ara nesneleri yazdırmak veya görselleştirmek ve nesnenin yapısının komut dosyanızdaki mantıkla tutarlı olduğundan emin olmak için bunları incelemektir. Daha açık belirtmek gerekirse, haritaya eklenen katmanların piksel değerlerini Kod Düzenleyici veya geemap denetleyici araçlarıyla inceleyebilirsiniz. Bir öğeyi yazdırırsanız özelliklerini açma düğmesini (▶) kullanarak genişlettiğinizden emin olun. Kontrol edilmesi gereken bazı noktalar şunlardır:
- Bant adları. Resim bandı adları kodunuzla eşleşiyor mu?
- Piksel değerleri. Verileriniz doğru aralığa sahip mi? Doğru şekilde maskelenmiş mi?
- Boş. Olmaması gereken bir şey null mi?
- Bedenler. Beden sıfır olarak ayarlanmışsa
aside()
Bir analizdeki her ara adımı, basılıp incelenebilmesi için bir değişkene koymak zahmetli olabilir. Uzun bir işlev çağrısı zincirindeki ara değerleri yazdırmak için aside()
yöntemini kullanabilirsiniz. Örneğin:
Kod Düzenleyici (JavaScript)
var image = ee.Image(ee.ImageCollection('COPERNICUS/S2') .filterBounds(ee.Geometry.Point([-12.29, 168.83])) .aside(print) .filterDate('2011-01-01', '2016-12-31') .first());
import ee import geemap.core as geemap
Colab (Python)
image = ee.Image( ee.ImageCollection('COPERNICUS/S2_HARMONIZED') .filterBounds(ee.Geometry.Point([-12.29, 168.83])) .aside(display) .filterDate('2011-01-01', '2016-12-31') .first() )
aside(print)
(JavaScript Kod Düzenleyici) ve aside(display)
(Python geemap) istemci tarafı işlevleri çağırdığını ve eşlenen işlevlerde yine de başarısız olacağını unutmayın. aside işlevini kullanıcı tanımlı işlevlerle de kullanabilirsiniz. Örneğin:
Kod Düzenleyici (JavaScript)
var composite = ee.ImageCollection('LANDSAT/LC08/C02/T1_TOA') .filterBounds(ee.Geometry.Point([106.91, 47.91])) .map(function(image) { return image.addBands(image.normalizedDifference(['B5', 'B4'])); }) .aside(Map.addLayer, {bands: ['B4', 'B3', 'B2'], max: 0.3}, 'collection') .qualityMosaic('nd'); Map.setCenter(106.91, 47.91, 11); Map.addLayer(composite, {bands: ['B4', 'B3', 'B2'], max: 0.3}, 'composite');
import ee import geemap.core as geemap
Colab (Python)
m = geemap.Map() m.set_center(106.91, 47.91, 11) composite = ( ee.ImageCollection('LANDSAT/LC08/C02/T1_TOA') .filterBounds(ee.Geometry.Point([106.91, 47.91])) .map(lambda image: image.addBands(image.normalizedDifference(['B5', 'B4']))) .aside(m.add_layer, {'bands': ['B4', 'B3', 'B2'], 'max': 0.3}, 'collection') .qualityMosaic('nd') ) m.add_layer(composite, {'bands': ['B4', 'B3', 'B2'], 'max': 0.3}, 'composite') m
first()
'te işlev çalıştırma
Yazdırma ve görselleştirme, mümkün olduğunda hata ayıklama için yararlıdır ancak bir koleksiyona eşlenen bir işlevde hata ayıklama yaparken eşlenen işlevler bölümünde açıklandığı gibi işlevde yazdıma yapamazsınız. Bu durumda, koleksiyondaki sorunlu öğeleri ayırmak ve eşlenen işlevi tek bir öğede test etmek faydalı olacaktır. İşlevi eşlemeden test ederken sorunu anlamak için yazdırma ifadelerini kullanabilirsiniz. Aşağıdaki örneği inceleyin.
Hata: Bu kod çalışmıyor.
Kod Düzenleyici (JavaScript)
var image = ee.Image( 'COPERNICUS/S2_HARMONIZED/20150821T111616_20160314T094808_T30UWU'); var someFeatures = ee.FeatureCollection([ ee.Feature(ee.Geometry.Point([-2.02, 48.43])), ee.Feature(ee.Geometry.Point([-2.80, 48.37])), ee.Feature(ee.Geometry.Point([-1.22, 48.29])), ee.Feature(ee.Geometry.Point([-1.73, 48.65])), ]); var problem = someFeatures.map(function(feature) { var dictionary = image.reduceRegion({ reducer: 'first', geometry: feature.geometry(), scale: 10, }); return feature.set({ result: ee.Number(dictionary.get('B5')) .divide(dictionary.get('B4')) }); }); // Error in map(ID=2): // Number.divide: Parameter 'left' is required. print(problem);
import ee import geemap.core as geemap
Colab (Python)
image = ee.Image( 'COPERNICUS/S2_HARMONIZED/20150821T111616_20160314T094808_T30UWU' ) some_features = ee.FeatureCollection([ ee.Feature(ee.Geometry.Point([-2.02, 48.43])), ee.Feature(ee.Geometry.Point([-2.80, 48.37])), ee.Feature(ee.Geometry.Point([-1.22, 48.29])), ee.Feature(ee.Geometry.Point([-1.73, 48.65])), ]) # Define a function to be mapped over the collection. def function_to_map(feature): dictionary = image.reduceRegion( reducer=ee.Reducer.first(), geometry=feature.geometry(), scale=10 ) return feature.set( {'result': ee.Number(dictionary.get('B5')).divide(dictionary.get('B4'))} ) problem = some_features.map(function_to_map) # EEException: Error in map(ID=2): # Number.divide: Parameter 'left' is required. print(problem.getInfo())
Bu hatayı gidermek için hatayı incelemeniz gerekir. Neyse ki bu faydalı hata mesajı, ID=2
ile ilgili bir sorun olduğunu size bildirir. Daha ayrıntılı bir inceleme yapmak için kodu biraz yeniden yapılandırmak faydalı olacaktır. Daha açık belirtmek gerekirse, bu bölümde açıklandığı gibi, bir koleksiyonla eşlendiğinde işlevde print ifadeleri bulunamaz. Hata ayıklamanın amacı, sorunlu özelliği tespit etmek ve işlevi bazı yazdırma ifadeleriyle birlikte çalıştırmaktır. Önceden kullanılan resim ve özelliklerle:
Kod Düzenleyici (JavaScript)
// Define a function to be mapped over the collection. var functionToMap = function(feature) { var dictionary = image.reduceRegion({ reducer: 'first', geometry: feature.geometry(), scale: 10, }); // Debug: print(dictionary); return feature.set({ result: ee.Number(dictionary.get('B5')) .divide(dictionary.get('B4')) }); }; // Isolate the feature that's creating problems. var badFeature = ee.Feature(someFeatures .filter(ee.Filter.eq('system:index', '2')) .first()); // Test the function with print statements added. functionToMap(badFeature); // Inspect the bad feature in relation to the image. Map.centerObject(badFeature, 11); Map.addLayer(badFeature, {}, 'bad feature'); Map.addLayer(image, {bands: ['B4', 'B3', 'B2'], max: 3000}, 'image');
import ee import geemap.core as geemap
Colab (Python)
# Define a function to be mapped over the collection. def function_to_map(feature): dictionary = image.reduceRegion( reducer=ee.Reducer.first(), geometry=feature.geometry(), scale=10 ) # Debug: display(dictionary) return feature.set( {'result': ee.Number(dictionary.get('B5')).divide(dictionary.get('B4'))} ) # Isolate the feature that's creating problems. bad_feature = ee.Feature( some_features.filter(ee.Filter.eq('system:index', '2')).first() ) # Test the function with print statements added. function_to_map(bad_feature) # Inspect the bad feature in relation to the image. m = geemap.Map() m.center_object(bad_feature, 11) m.add_layer(bad_feature, {}, 'bad feature') m.add_layer(image, {'bands': ['B4', 'B3', 'B2'], 'max': 3000}, 'image') m
Artık işlev yalnızca bir özellikte çalıştırıldığı için içine bir print ("display" for Python geemap) çağrısı koyabilirsiniz. reduceRegion()
tarafından döndürülen nesnenin her bant için null değerine sahip olduğunu keşfetmek amacıyla basılı nesneyi inceleyin. Bölme işleminin neden başarısız olduğu bu şekilde açıklanabilir: null değerini null değerine bölemezsiniz. Neden baştan null?
İncelemek için giriş resmini ve hatalı özelliği haritaya ekleyin ve hatalı özelliği merkeze alın. Bu sırada, sorunun noktanın görüntünün sınırları dışında olmasından kaynaklandığını keşfedersiniz. Bu keşfe göre hata ayıklanmış kod şu şekildedir:
Kod Düzenleyici (JavaScript)
var functionToMap = function(feature) { var dictionary = image.reduceRegion({ reducer: 'first', geometry: feature.geometry(), scale: 10, }); return feature.set({ result: ee.Number(dictionary.get('B5')) .divide(dictionary.get('B4')) }); }; var noProblem = someFeatures .filterBounds(image.geometry()) .map(functionToMap); print(noProblem);
import ee import geemap.core as geemap
Colab (Python)
def function_to_map(feature): dictionary = image.reduceRegion( reducer=ee.Reducer.first(), geometry=feature.geometry(), scale=10 ) return feature.set( {'result': ee.Number(dictionary.get('B5')).divide(dictionary.get('B4'))} ) no_problem = some_features.filterBounds(image.geometry()).map(function_to_map) display(no_problem)
Profiler
Profilleyici, etkinken yapılan hesaplamadan kaynaklanan EECU süresi ve bellek kullanımı (algoritma ve öğe başına) hakkında bilgi sağlar. En fazla kaynak kullanan işlemler hakkında bilgi edinmek için profilleyicinin üst kısmındaki girişleri arayın. Uzun süre çalışan veya verimsiz komut dosyalarında, profiler'ın üst kısmındaki girişler, komut dosyasını optimize etmek için çabaların nereye odaklanacağı hakkında ipuçları sağlar. Önemli not: Profilleyicinin kendisi komut dosyasının performansını etkiler. Bu nedenle, yalnızca gerektiğinde çalıştırmanız gerekir.