【初心者向け】 Sagemaker 地理空間機能を使ってみた

## 目次

1. [はじめに](#はじめに)
2. [SageMaker 地理空間機能を使ってみる](#sagemaker-地理空間機能を使ってみる)
3. [SageMaker 地理空間機能の環境削除](#sagemaker-地理空間機能の環境削除)
4. [まとめ](#まとめ)

## はじめに

Sentinel2やLandsat8などの無料衛星データを取得しようと思うと、Copernicus Open Access HubやUSGS Earth Explorerなどの公式サイトからデータをダウンロードする必要があり大変ですよね。

SageMaker 地理空間機能を使用すると簡単にデータを取得、分析することができるようです。そこで今回は、地理空間機能を使用して衛星データを取得しました。

**※データの対象は世界中全てですが、2024年11月現在SageMaker 地理空間機能は、米国西部（オレゴン：us-west-2）リージョンでのみ利用可能です。**

https://aws.amazon.com/jp/sagemaker/geospatial/

https://docs.aws.amazon.com/ja_jp/sagemaker/latest/dg/geospatial.html

コードに関しては、まだまだ初学者なので間違いや改善点があれば、ご指摘いただけると幸いです。

## SageMaker 地理空間機能を使ってみる

### 1. SageMaker 地理空間機能の準備

SageMaker 地理空間機能は、SageMaker Studio Classicのノートブックインスタンス経由でGeospatial 1.0 イメージを用いて使用します。

![地理空間機能設定_4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3635206/3e792667-f1d8-964a-041c-cd69159cc662.png)


まずは、開発者ガイドの「[SageMaker 地理空間の初めてのユーザーですか？](https://docs.aws.amazon.com/ja_jp/sagemaker/latest/dg/geospatial.html)」に記載の手順に従ってSageMakerのセットアップを行います。

### 2. 衛星データの確認

使用する準備ができたら、早速ノートブックを作成していきましょう。

AWSのRaster Data Collectionにあるデータセットを利用します。まずは、どんなデータセットがあるのか確認するためのノートブックを作成します。

[Sentinel-2 ラスターのデータ収集にアクセスし、土地セグメンテーションを実行する地球観測ジョブを作成する](https://docs.aws.amazon.com/ja_jp/sagemaker/latest/dg/geospatial-demo.html)を読みながら進めていきました。

```python
# SageMaker Geospatialのクライアントを作成
import boto3
import sagemaker
import sagemaker_geospatial_map
import json

session = boto3.Session(region_name='us-west-2')
execution_role = sagemaker.get_execution_role()
geospatial_client = session.client(service_name="sagemaker-geospatial")
paginator = geospatial_client.get_paginator("list_raster_data_collections")
```

続いて、利用可能なデータセットを表示します。

```python
# 利用可能なデータセットをリスト化
page_iterator = paginator.paginate()

results = []
for page in page_iterator:
    results.append(page['RasterDataCollectionSummaries'])
```

```python
# 利用可能なデータセットを出力
for collection in results[0]:
    print(f"Name: {collection['Name']}, ARN: {collection['Arn']}")
```

実行結果は以下のようになります。(ARNは一部伏せています)

```text
Name: Copernicus DEM GLO-30, ARN: <arn:aws:sagemaker-geospatial:us-west-2:012345678910:raster-data-collection/public/...
Name: Copernicus DEM GLO-90, ARN: arn:aws:sagemaker-geospatial:us-west-2:012345678910:raster-data-collection/public/...
Name: Landsat Collection 2 Level-2 Science Products, ARN: arn:aws:sagemaker-geospatial:us-west-2:012345678910:raster-data-collection/public/...
Name: National Agriculture Imagery Program, ARN: arn:aws:sagemaker-geospatial:us-west-2:012345678910:raster-data-collection/public/...
Name: Sentinel 1 GRD, ARN: arn:aws:sagemaker-geospatial:us-west-2:012345678910:raster-data-collection/public/...
Name: Sentinel 2 L2A COGs, ARN: arn:aws:sagemaker-geospatial:us-west-2:012345678910:raster-data-collection/public/...
```

これにより利用可能なデータセットが表示され、それぞれのARNが取得できます。

続いて、Sentinel 2 L2A COGsデータセットからデータを取得します。まずは、データを探すためのクエリを作成します。

```python
# Sentinel 2 L2A のARNを指定
sentinel2_arn = "arn:aws:sagemaker-geospatial:us-west-2:012345678910:raster-data-collection/public/..."
# 雲のカバー率
cloud_cover_property = {
    "EoCloudCover": {
        "LowerBound": 0,
        "UpperBound": 20
    },
}
# AOIを指定(例はオレゴン州)
OREGON = [
     [-123.9150942493107, 46.183629329503916],
     [-124.1897524462052, 42.085988872609015],
     [-117.14751627783, 42.17561276955665],
     [-117.0376529990722, 45.801994745667486],
     [-123.9150942493107, 46.183629329503916]
]
# 検索のクエリを指定
search_rdc_query = {
    "AreaOfInterest": {
        "AreaOfInterestGeometry": {
            "PolygonGeometry": {
                "Coordinates": [OREGON]
            }
        }
    },
    "TimeRangeFilter": {
        "StartTime": f'2024-06-01T00:00:00Z',
        "EndTime": f'2024-8-30T23:59:59Z'
    },
    "PropertyFilters": {
        "Properties": [
            {
                "Property": cloud_cover_property
            }
        ],
        "LogicalOperator": "AND"
    },
}
```

Sentinel2のARNとクエリをセットし、衛星データを探すためのジョブを実行します。

```python
search_rdc_response = geospatial_client.search_raster_data_collection(
    Arn=sentinel2_arn,
    RasterDataCollectionQuery=search_rdc_query
)
```

探したデータがいくつあるのかリストに格納して調べます。以下のコードを実行することで、ジョブが実行中かどうかを確認できます。

```python
items_list = []
while search_rdc_response.get('NextToken'):
    items_list.extend(search_rdc_response['Items'])
    search_rdc_response = geospatial_client.search_raster_data_collection(
        Arn=use_arn,
        RasterDataCollectionQuery=search_rdc_query,
        NextToken=search_rdc_response['NextToken']
    )
# 取得したデータ数を表示
print (len(items_list))
```

これらの処理を実行することで、どれくらいの衛星データが取得できるのか確認できます。

### 3. 衛星データの取得

続いて、衛星データをダウンロードします。先ほど、作成したリスト内にあるURLから、urllibモジュールのurlretrieve()を使用することでローカルディレクトリに保存できます。

```python
import os
from urllib import request
import tifffile
import matplotlib.pyplot as plt

# データを保存するディレクトリを作成
image_dir = "./images"
os.makedirs(image_dir, exist_ok=True)

# リストからURLを取得
image_url = items_list[0]["Assets"]["visual"]["Href"]
# URLから画像IDを取得
img_id = image_url.split("/")[-2]
# ダウンロード先のパスを指定
path_to_image = image_dir + "/" + img_id + "_TCI.tif"
# 画像をダウンロード
response = request.urlretrieve(image_url, path_to_image)
print("Downloaded image: " + img_id)

# 画像を表示
tci = tifffile.imread(path_to_image)
plt.figure(figsize=(6, 6))
plt.imshow(tci)
plt.show()
```

以上が、衛星データの取得までの手順です。

## SageMaker 地理空間機能の環境削除

地理空間学習機能向けのSageMakerは、無料利用枠が60日間用意されていますが、環境を削除せずそのままにしておくと課金が発生します。

１ユーザーにつき USD $150固定でかかるので、使用後は環境を削除することをお勧めします。

ドメインの削除は、[Amazon SageMaker ドメインを削除する](https://docs.aws.amazon.com/ja_jp/sagemaker/latest/dg/gs-studio-delete-domain.html)に沿って行います。

コンソールからドメインを削除した後、Cloud shell から AWS CLIのコマンドを実行して確認しました。

```bash
# アカウント内のドメインのリストを取得
aws --region Region sagemaker list-domains

# 削除するドメインのアプリケーションのリストを取得
aws --region Region sagemaker list-apps \
    --domain-id-equals DomainId

# ドメインのユーザープロファイルのリストを取得
aws --region Region sagemaker list-user-profiles \
    --domain-id-equals DomainId

# ドメイン内の共有スペースのリストを取得
aws --region Region sagemaker list-spaces \
    --domain-id DomainId
```

以上のコマンドを実行し、ドメインが削除されていることを確認しました。

しかし、ドメインを削除しても、SageMaker Studio Classicのノートブックインスタンスが残っている場合があります。その場合は、ノートブックインスタンスを削除する必要があります。

また、実行したジョブやモデルも削除しなければ課金され続けるので削除が必要です。私もEarthObservationJobが残っていることに気づかず、課金されてしまいました。早めに気づいて良かったですが・・・詳しくは「[SageMaker 地理空間機能　環境削除の備忘録](https://qiita.com/tosimitsu104/private/3a373cab8fd252a5c9c3)」の記事を作成しましたので、ご参考にしてください。

以下が、残ったジョブの削除方法です。

```bash
# ジョブのリストを取得
aws sagemaker-geospatial list-earth-observation-jobs --output json > earth_observation jobs. json

# ジョブのarnをtextファイルに保存
jq -r ' EarthObservationJobSummaries[].Arn' earth_observation_jobs.json > job_arns.txt

# arn分の削除を実行
while read -r arn; do
    aws sagemaker-geospatial delete-earth-observation-job --arn "$arn"
done < job_arns.txt

# ジョブのリストを再取得し残っていないか確認する
aws
sagemaker-geospatial list-earth-observation-jobs --output json > earth_observation_jobs_after.json
```

## まとめ

今回は、SageMaker 地理空間機能を使って衛星データを取得する方法を試してみました。SageMaker 地理空間機能は、米国西部（オレゴン：us-west-2）リージョンでのみ利用可能ですが、無料利用枠が60日間用意されているので、気軽に試すことができます。これによりデータ収集のハードルがかなり下がるのではないでしょうか。

まだまだ、使えていない機能はたくさんあるので、今後もSageMakerを使っていろいろなことに挑戦していきたいと思います。