함수형 프로그래밍 개념

함수형 프로그래밍 소개

Earth Engine은 병렬 처리 시스템을 사용하여 많은 머신에서 계산을 실행합니다. 이러한 처리를 지원하기 위해 Earth Engine은 참조 투명성 및 지연 평가와 같이 함수형 언어에서 일반적으로 사용되는 표준 기법을 활용하여 상당한 최적화 및 효율성 향상을 달성합니다.

함수형 프로그래밍을 절차형 프로그래밍과 구분하는 주요 개념은 부작용의 부재입니다. 즉, 작성하는 함수가 함수 외부의 데이터를 사용하거나 업데이트하지 않습니다. 아래 예에서 볼 수 있듯이 부작용이 없는 함수를 사용하여 문제를 해결할 수 있도록 문제를 재구성할 수 있습니다. 이러한 함수는 병렬로 실행하는 데 훨씬 적합합니다.

For 루프

Earth Engine에서는 for 루프를 사용하지 않는 것이 좋습니다. 각 요소에 독립적으로 적용할 수 있는 함수를 지정하는 map() 작업을 사용하여 동일한 결과를 얻을 수 있습니다. 이를 통해 시스템은 처리를 여러 머신에 분산할 수 있습니다.

아래 예에서는 숫자 목록을 가져와 map()를 사용하여 각 숫자의 제곱이 포함된 다른 목록을 만드는 방법을 보여줍니다.

코드 편집기 (JavaScript)

// This generates a list of numbers from 1 to 10.
var myList = ee.List.sequence(1, 10);

// The map() operation takes a function that works on each element independently
// and returns a value. You define a function that can be applied to the input.
var computeSquares = function(number) {
  // We define the operation using the EE API.
  return ee.Number(number).pow(2);
};

// Apply your function to each item in the list by using the map() function.
var squares = myList.map(computeSquares);
print(squares);  // [1, 4, 9, 16, 25, 36, 49, 64, 81]

If/Else 조건

절차형 프로그래밍 패러다임에 익숙한 신규 사용자가 겪는 또 다른 일반적인 문제는 Earth Engine에서 if/else 조건 연산자를 올바르게 사용하는 것입니다. API는 ee.Algorithms.If() 알고리즘을 제공하지만 map() 및 필터를 사용하는 더 기능적인 접근 방식을 사용하는 것이 좋습니다. Earth Engine은 지연된 실행을 사용합니다. 즉, 표현식의 평가가 실현된 값이 실제로 필요할 때까지 지연됩니다. 경우에 따라 이러한 유형의 실행 모델은 ee.Algorithms.If() 문의 true 및 false 대안을 모두 평가합니다. 이로 인해 표현식과 표현식을 실행하는 데 필요한 리소스에 따라 추가 계산과 메모리 사용량이 발생할 수 있습니다.

위 예시의 변형을 해결하려고 한다고 가정해 보겠습니다. 여기서 작업은 홀수의 제곱만 계산하는 것입니다. if/else 조건 없이 이 문제를 해결하는 기능적 접근 방식은 아래에 나와 있습니다.

코드 편집기 (JavaScript)

// The following function determines if a number is even or odd.  The mod(2)
// function returns 0 if the number is even and 1 if it is odd (the remainder
// after dividing by 2).  The input is multiplied by this remainder so even
// numbers get set to 0 and odd numbers are left unchanged.
var getOddNumbers = function(number) {
  number = ee.Number(number);   // Cast the input to a Number so we can use mod.
  var remainder = number.mod(2);
  return number.multiply(remainder);
};

var newList = myList.map(getOddNumbers);

// Remove the 0 values.
var oddNumbers = newList.removeAll([0]);

var squares = oddNumbers.map(computeSquares);
print(squares);  // [1, 9, 25, 49, 81]

이 패러다임은 컬렉션을 사용할 때 특히 적용됩니다. 일부 조건에 따라 컬렉션에 다른 알고리즘을 적용하려면 먼저 조건에 따라 컬렉션을 필터링한 다음 각 하위 집합에 다른 함수를 map()하는 것이 좋습니다. 이를 통해 시스템이 작업을 병렬화할 수 있습니다. 예를 들면 다음과 같습니다.

코드 편집기 (JavaScript)

// Import Landsat 8 TOA collection and filter to 2018 images.
var collection = ee.ImageCollection('LANDSAT/LC08/C02/T1_TOA')
  .filterDate('2018-01-01', '2019-01-01');

// Divide the collection into 2 subsets and apply a different algorithm on them.
var subset1 = collection.filter(ee.Filter.lt('SUN_ELEVATION', 40));
var subset2 = collection.filter(ee.Filter.gte('SUN_ELEVATION', 40));

// Multiply all images in subset1 collection by 2;
// do nothing to subset2 collection.
var processed1 = subset1.map(function(image) {
  return image.multiply(2);
});
var processed2 = subset2;

// Merge the collections to get a single collection.
var final = processed1.merge(processed2);
print('Original collection size', collection.size());
print('Processed collection size', final.size());

누적 반복

각 반복의 결과가 후속 반복에서 사용되는 순차적 작업을 실행해야 할 수 있습니다. Earth Engine은 이러한 작업을 위한 iterate() 메서드를 제공합니다. iterate()는 순차적으로 실행되므로 대규모 작업에서는 속도가 느립니다. map() 및 필터를 사용하여 원하는 출력을 얻을 수 없는 경우에만 사용하세요.

iterate()의 좋은 예는 피보나치 수열을 만드는 것입니다. 여기서 계열의 각 숫자는 이전 두 숫자의 합입니다. iterate() 함수는 함수 (알고리즘)와 시작 값이라는 두 개의 인수를 사용합니다. 함수 자체는 반복의 현재 값과 이전 반복의 결과라는 두 값을 전달받습니다. 다음 예에서는 Earth Engine에서 피보나치 수열을 구현하는 방법을 보여줍니다.

코드 편집기 (JavaScript)

var algorithm = function(current, previous) {
  previous = ee.List(previous);
  var n1 = ee.Number(previous.get(-1));
  var n2 = ee.Number(previous.get(-2));
  return previous.add(n1.add(n2));
};

// Compute 10 iterations.
var numIteration = ee.List.repeat(1, 10);
var start = [0, 1];
var sequence = numIteration.iterate(algorithm, start);
print(sequence);  // [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]

이제 JavaScript 개념을 잘 이해했으므로 API 튜토리얼에서 Earth Engine API의 지리 공간 기능을 소개합니다.