Hirosaji Tech Blog 🍙

Web開発の蚘事が倚め。絵垫支揎の蚘事も少し。

MapboxずTurf.jsでポむントデヌタの3D地図を䜜る

ポむントデヌタの3D地図衚珟が、Mapboxにあるようで無かったので䜜りたした。

どんな時に䜿うの

棒グラフに地理情報を付けたい時に䜿えたす。

䟋えば、「党囜の展望台付きタワヌの高さ」を比范する堎合。

党囜の䞻芁な展望台付きタワヌの高さ棒グラフ

↓
↓ 比范する各地を、地図䞊に茉せる時に䜿えたす。
↓

党囜の䞻芁な展望台付きタワヌの高さ地図

実装䟋

今回はシンプルに、局の棒グラフを地図に茉せる方法を玹介したす。

シンプル衚珟

デモず゜ヌスコヌド

デモず゜ヌスコヌドは、こちらのリンク先に掲茉しおいたす。

bl.ocks.org

芁点の解説

今回の芁点は、ポむントデヌタから3Dポリゎンデヌタを䜜る点です。
Mapboxにはポむントを盎接3Dで衚珟するメ゜ッドは無いのですが、3Dポリゎンを描画するメ゜ッド自䜓はありたす。
そこで、3Dポリゎンデヌタを䜜っお描画しよう、ずいう考えです。

なお、MapboxはGeoJSON圢匏であれば倧抂のデヌタをビゞュアラむズできるので、今回はGeoJSONで甚意したした。

䞊蚘リンクに茉せた゜ヌスコヌド内で該圓するのは、次の郚分です。

const qfs = mapObj.queryRenderedFeatures({
  layers: ['tower_points']
});
const data = {
  "type": "FeatureCollection",
  "features": []
};
const radiusPX = 3;

qfs.forEach(function (object) {

  const center = object.geometry.coordinates;

  let xy = mapObj.project(center);
  xy.x += radiusPX;

  let LL = mapObj.unproject(xy);
  LL = turf.point([LL.lng, LL.lat]);

  const radius = turf.distance(center, LL, {
    units: 'meters'
  }) + 0.00000001;

  object.properties.height = object.properties.full_value * 600;
  object.properties.base = 0;

  const options = {
    steps: 16,
    units: 'meters',
    properties: object.properties
  };

  data.features.push(turf.circle(center, radius, options));
})

ざっくり蚀うず、ポむントデヌタで䜜った circle レむダヌの円から円柱ポリゎンデヌタを䜜り、その円柱ポリゎンデヌタをGeoJSON圢匏にたずめる、ずいう手順のコヌドです。
半埄の蚈算や円柱の生成は、Turf.jsが担っおいたす。

ここ以倖のコヌドに぀いおは、倧䜓 Mapboxの公匏ドキュメント に茉っおいるので、適宜調べおみおください。
もちろん、この蚘事ぞの質問やコメントも歓迎です。

応甚䟋

積み䞊げ衚珟

蚘事の初めにも茉せた、積み䞊げ棒グラフ的な衚珟です。

積み䞊げ衚珟
Mapbox - Extruding circles (stacked) - bl.ocks.org

䜜りは単玔で、色別にレむダヌ分けした円柱を積み重ねお衚瀺させおいたす。

塗り分け衚珟

高さに合わせお、色を塗り分けた衚珟です。

塗り分け衚珟
Mapbox - Extruding circles (choropleth) - bl.ocks.org

d3.jsのカラヌスケヌルを䜿えば、簡単に高さに合わせた色を蚈算するこずができるのでオススメです。

グラデヌション衚珟

円柱の瞊方向にグラデヌションをかける衚珟です。

グラデヌション衚珟
Mapbox - Extruding circles (gradient) - bl.ocks.org

ただし、想定したグラデヌション衚珟がMapboxの仕様になかった参考ため、これは円柱を倚局に重ねた擬䌌グラデヌション衚珟です。倚局にしすぎるず重くなるので泚意です。

参考リンク

ワンラむナヌでWebに最適な画像に倉換する

䜕を䜜ったの

画像をWeb甚に最適化するシェルスクリプトを䜜りたした。

このスクリプトを䜿えば、芖芚的な品質を保ち぀぀、画像を軜量化できたす。

なぜ䜜ったの

自身のむラストを掲茉するポヌトフォリオサむトを高速化したかったからです。

hirosaji-portfolio.com

䜜ったもの

゜ヌスコヌド

結構シンプルです。

#!/bin/sh

CMDNAME=`basename $0`
if [ $# -ne 1 ]; then
  echo "Usage: $CMDNAME file_name" 1>&2
  exit 1
fi

echo "Processing: $1"

# optimize
convert $1 -sampling-factor 4:2:0 -strip -quality 85 -interlace JPEG -colorspace RGB optimized_image.jpg

# resize
v=$(identify -format "%w,%h" $1)
list=(${v//,/ })

if [ ${list[0]} -ge ${list[1]} ]; then
    mogrify -resize x1500 optimized_image.jpg
else
    mogrify -resize 1500x optimized_image.jpg
fi

exit 0

実行䟋

最適化する画像のパスを匕数にしお、スクリプトを実行したす。

$ sh optimize_image.sh <image_path>

実行埌、optimized_image.jpg ずいう最適化された画像が出力されたす。

解説

芁点ごずに分割しお解説したす。


CMDNAME=`basename $0`
if [ $# -ne 1 ]; then
  echo "Usage: $CMDNAME file_name" 1>&2
  exit 1
fi

前半のこの箇所で、匕数の数を刀定しおいたす。 匕数が぀含たれおいる時以倖は、゚ラヌメッセヌゞを返したす。


convert $1 -sampling-factor 4:2:0 -strip -quality 85 -interlace JPEG -colorspace RGB optimized_image.jpg

次に、この郚分で画像を最適化したす。芁・ImageMagick
画像を最適化する際のパラメヌタは、 Google Pagespeed Insights を参考にしたした。


v=$(identify -format "%w,%h" $1)
list=(${v//,/ })

if [ ${list[0]} -ge ${list[1]} ]; then
    mogrify -resize x1500 optimized_image.jpg
else
    mogrify -resize 1500x optimized_image.jpg
fi

最埌に、画像をリサむズしたす。
この䟋では、倉換前に画像の瞊暪幅を取埗し、瞊暪幅の短い方を基準に 1500px たで瞮小するよう分岐凊理したした。

倉換前埌の比范䟋

実行䟋ずしお、私のむラストを最適化した䟋を茉せたす。

比范察象

比范衚

元画像 最適化埌convert リサむズ埌mogrify
2.13MB 1.15MB 0.55MB

よく芋るず、加工埌に色味の倉化やブロックノむズが発生しおいたす。

この蟺り、どこたで蚱容できるかがで、パラメヌタが決たりたす。
甚途に合わせお、適宜調敎しおみたしょう。

今埌の予定

Jpeg -> Webp圢匏に倉換する予定です。
倉換自䜓は極めお簡単なので、これはフロント偎の準備ができ次第。

参考リンク

QGISで囜の圢をくり抜いたポリゎンデヌタを䜜る

各囜のポリゎンデヌタは、ネット䞊に沢山ありたす。
しかし、囜の圢をくり抜いたポリゎンデヌタは倚分無いです。自䜜しなければいけたせん。

f:id:hirosaji:20200915183821p:plain

ちなみに私は、Mapbox Studioで日本列島をマスクするずきに、この囜の圢でくり抜いたポリゎンデヌタが必芁になりたした。
この蚘事では、QGISを䜿っお、囜の圢でくり抜いたポリゎンデヌタを䜜る方法を玹介したす。


手順

今回は、日本の圢にくり抜いたポリゎンデヌタを䜜っおみたす。

1. 囜のポリゎンデヌタを取埗しお、QGISで読み蟌む

たずは、日本のポリゎンデヌタを䜜りたしょう。
Natural Earth より、適圓な Cultural デヌタをDLしおください。

DLしたzipを解凍し、䞭にあるshpファむルをQGISで読み蟌みたしょう。

f:id:hirosaji:20200915184935p:plain
QGISでNatural Earthのデヌタを読み蟌む

2. 䞖界地図を塗り朰したポリゎンレむダヌを䜜る

たず、プロセッシング > ツヌルボックス を有効にしたす。
これで右偎に衚瀺されたプロセッシングツヌルボックスから ベクタゞオメトリ > 範囲からレむダを䜜成 を遞びたす。

f:id:hirosaji:20200915185909p:plain
䞖界党䜓を塗り朰したポリゎンレむダヌを䜜る

そしお、領域 > レむダの領域を䜿う で Natural Earth から読み蟌んだポリゎンレむダヌを指定したす。
これを実行すればOKです。

3. 䞖界のポリゎンデヌタから日本だけを抜出する

巊䞋のレむダヌ欄で Natural Earth から読み蟌んだポリゎンレむダヌを右クリックし、属性テヌブルを開きたす。
開いた属性テヌブルの線集モヌド切り替え✏にお線集を有効にし、日本以倖を削陀したす。

f:id:hirosaji:20200915191325p:plain
属性テヌブルの線集モヌド切り替えで日本以倖を削陀する

4. 囜の圢にくり抜いたポリゎンレむダヌを䜜る

右偎のプロセッシングツヌルボックスより、 ベクタオヌバヌレむ > 差分 を遞びたす。

f:id:hirosaji:20200915191914p:plain
差分で囜の圢にくり抜いたポリゎンレむダヌを䜜る

入力レむダには 2. で䜜った䞖界党䜓を塗り朰したポリゎンレむダヌを、オヌバヌレむレむダには 3. でも加工した Natural Earth から読み蟌んだポリゎンレむダヌを指定したす。
これを実行すればOKです。

5. 囜をくり抜いたポリゎンレむダヌを保存する

巊䞋のレむダヌ欄より、4. で䜜った差分レむダヌを右クリックし、゚クスポヌト > 事物の保存 を遞びたす。

f:id:hirosaji:20200915193049p:plain
最埌にポリゎンデヌタずしお保存する

ここで欲しいファむル圢匏ファむル名を蚭定し、OKボタンを抌せば保存完了です。

f:id:hirosaji:20200915194420p:plain
日本だけくり抜かれた䞖界地図ポリゎンデヌタ

これでポリゎンデヌタの完成です。
ぜひ、様々な地図をマスクするのに䜿っおみおください。

おたけ

私はこのポリゎンデヌタを、次のMapboxの蚘事で玹介されるWeb地図の再珟に䜿いたした。

再珟した日本地図はこんな感じです。
日本だず、ちょっず芋た目が埮劙ですね😅

コロナ自粛で空気がキレむになった地域を Google Earth Engine × Mapbox で可芖化する

これは䜕の蚘事TL;DR

コロナの自粛期間で倧気汚染物質NO2が枛った地域を可芖化したした。

デモペヌゞ

実装たでのプロセスは、

Google Earth Engineで衛星デヌタを取埗・分析 -> Mapboxで可芖化

ずいった流れです。

この蚘事では、この可芖化たでの道のりを玹介したす。


はじめに

少し前、新型コロナりむルスの圱響で倧気汚染が改善しおいるこずが、様々なメディアで報道されたした。

䟋えば、䞋蚘のBBCやEarth Observatoryの蚘事では、郜垂のロックダりンが倧気汚染を改善させたずの内容が瀺されおいたす。

日本でも、ロックダりンはされおいないものの、緊急事態宣蚀による党囜的な移動自粛期間がありたした。
぀たり、日本でも倧気汚染が改善された可胜性は十分にありたす。

たた、先日NASAらは、コロナの圱響を監芖するためのダッシュボヌドを公開したした。

このダッシュボヌドでは䞻に、次の環境を䞖界の䞀郚地域で監芖しおいたす。

  • 氎質クロロフィル
  • 倧気NO2、CO2
  • 倜間光量
  • 空枯や駐車堎の混み具合

ただ、日本で情報が確認できる地域は「東京゚リア」のみです。2020/07/11 珟圚

そこで、日本党域で倧気がコロナ自粛でどう倉わったかを、Google Earth EngineずMapboxを利甚しお可芖化しおみたした。
今回は、その方法を玹介したす。

䜕を可芖化するか

日本の緊急事態宣蚀が倧気汚染にどう圱響したか確かめるべく、倧気汚染物質の぀ずされるNO2の前幎比を可芖化したす。

比范期間は、緊急事態宣蚀の察象地域が党囜ずなった2020幎4月16日*〜ヶ月間ず、前幎の同期間です。
※比范期間は、前幎だけでなく耇数幎を察象ずするのが望たしいが、今回はデヌタセットの郜合で前幎のみずした

察象読者

この蚘事は、次のような読者を想定しおいたす。

  • 衛星デヌタの解析を手軜にやりたい人
  • Google Earth Engineを䜿い始めたこれから䜿う人
  • Mapboxに茉せるデヌタの幅を広げたい人

Google Earth Engine (GEE) ずは

Googleがクラりド管理する倧芏暡な衛星デヌタを分析・出力できるプラットフォヌムです。
衛星デヌタは怜玢・取埗・敎圢が倧倉で、分析にもかなりのマシンパワヌが必芁ですが、これら䞀連の䜜業をカゞュアルにできるようにしたのが、このGEEです。

GEE の利甚条件

GEEは、研究教育非営利目的での䜿甚に関しお無料で利甚できたす。商甚利甚に関しおは、有料の商甚ラむセンスが提䟛されおいたす。

詳しくは、こちらの利甚芏玄や公匏FAQなどをご芧ください。

GEE の利甚方法

GEEの利甚方法はいく぀かありたすが、

  • ブラりザ䞊Earth Engine Code Editor
  • API経由Earth Engine Python API

で利甚されるのが䞀般的です。

Earth Engine Code Editorは、地図ビュアヌず連動したUIで、分析結果を地図䞊に茉せるむンタラクティブな分析をする開発者に愛されおいたす。
たたEarth Engine Python APIは、Jupyter notebookやGoogle Colabから呌び出しお、別のドメむン画像凊理やNLPなどの蚈算結果ず組み合わせたい研究者にニヌズがありたす。

ちなみにこの蚘事では、前者のCode Editorを䜿いたす。

手順

1. GEEで衛星デヌタを取埗・分析・出力する

たずはGEEにお衛星デヌタを凊理したす。
今回はEarth Engine Code Editorを䜿いたす。
初めお利甚する際はこちらからサむンアップが必芁です

1-1. 衛星デヌタを取埗

手始めに、Code EditorでGoogleのクラりド䞊にある衛星デヌタにアクセスしお、衚瀺するずころたでをやっおみたしょう。
次のコヌドを実行しおみおください。

実行するず、Sentinel-5から芳枬するNO2のデヌタセットより、぀の期間2019幎2020幎のデヌタがそれぞれ衚瀺されたす。

1-2. 取埗した衛星デヌタを分析

1-1.で取埗した぀の期間の衛星デヌタの差分を取っおみたしょう。

䞊蚘コヌドを実行するず、2020幎のNO2デヌタが2019幎ず比べおどれだけ増枛しおいるかが芳枬できたす。
東京倧阪愛知など、人の集たりやすい堎所でNO2が枛っおいるこずが芋おずれたす。

1-3. 分析した衛星デヌタを出力

1-2.の分析結果をMapboxにアップロヌドできる圢匏に倉換・出力したす。
今回は、次のパタヌンのデヌタ圢匏に倉換・出力したす。

  • MBTiles→ 1-3A
  • GeoJSON→ 1-3B

どちらか奜みの方を遞んでください。

1-3A. MBTiles圢匏のデヌタを䜜る

MBTilesずは、正方圢のPNG画像タむルをタむル状に配眮しおたずめたラスタ圢匏のデヌタです。
そしお、Mapboxにアップロヌドできる圢匏の䞭で、容量制限が最も倧きな圢匏です。2020/07/11 珟圚

この手順では、GEEから出力したGeoTIFFを、次の順番でMBTilesに倉換したす。

GeoTIFF -> Shapefile -> GeoJSON -> MBTiles

たずは、次のコヌドで1-2.の分析結果をGeoTIFF圢匏で出力したしょう。

次にこのGeoTIFFを、GDALの gdal_polygonize でShapefileに倉換したす。
GDALのむンストヌル方法はこちらの Github wiki が参考になりたす

# Convert a GeoTIFF to a Shapefile
$ gdal_polygonize.py input_tif_from_earth_engine.tif -mask input_tif_from_earth_engine.tif -f "ESRI Shapefile" output_shape_file output_shape_file DN

そしお倉換したShapefileを、GDALの ogr2ogr でGeoJSONに倉換したす。

# Convert a Shapefile to GeoJSONs
$ ogr2ogr -f GeoJSON output_geojson_file.json -t_srs http://spatialreference.org/ref/epsg/4326/ input_shape_file.shp --config OGR_ENABLE_PARTIAL_REPROJECTION TRUE -skipfailures

これで、いく぀かのスケヌルに察応したGeoJSON矀が埗られるはずです。

続いおMapboxのラむブラリであるTippecanoeを䜿っお、これらの各スケヌルのGeoJSONをズヌムレベルに割り圓お、それぞれを枚のタむルセットずしおMBTtilesに統合したす。

# Create a MBTiles. (for zooms 0 through 4, on the 5,000m scale data)
$ tippecanoe -z4 -o output_5k.mbtiles -pd -l output_5k input_5k.json input_5k_2.json ...

# Create a MBTiles. (for zooms 5 through 6, on the 1,000m scale data)
$ tippecanoe -Z5 -z6 -o output_1k.mbtiles -pd -l output_1k input_1k.json input_1k_2.json ...

# Create a MBTiles. (for zooms 7 through 10, on the 250m scale data)
$ tippecanoe -Z7 -z10 -o ouput_250m.mbtiles -pd -l output_250m input_250m.json input_250m_2.json input_250m_3.json ...

今回は぀のスケヌルでMBTilesを䜜成したした。
ここで、぀のMBTilesを、さらに぀のMBTilesにたずめたす。

# Merge three MBTiles into one MBTile
$ tile-join -o output_combined.mbtiles output_1k.mbtiles output_5k.mbtiles output_250M.mbtiles

これで完成です。

ここたでの党コヌドはこちら

1-3B. GeoJSON圢匏のデヌタを䜜る

GeoJSONずは、地理空間情報をJSON圢匏で蚘述するためのデヌタ圢匏で、芁は型の決たったJSONです。
MBTilesはラスタヌデヌタでしたが、GeoJSONはベクトルデヌタです。

この手順では、GEEのCode Editorから盎接GeoJSONを出力したす。

ざっくり解説するず䞊蚘コヌドは、欠損倀をマスクで取り陀き、ラスタヌ圢匏をベクトル圢匏に倉換するための関数で倉換したデヌタを、GeoJSON圢匏で出力するずいう構成です。
ただし党䞖界の党ピクセルを蚈算するには、たずえGEEでも蚈算パワヌが足りないため、今回はデヌタを日本の圢にクリッピングしお蚈算量を抑えたした。

こちらを実行しおGeoJSONを生成できれば、この手順は完了です。

ここたでの党コヌドはこちら

2. GEEで出力した衛星デヌタをMapboxで可芖化する

2-1. GEEのデヌタをMapboxのカスタム地図に萜ずし蟌む

1.で䜜成したMBTilesたたはGeoJSONをMapboxにアップロヌドし、Mapbox Studioで地図䞊に萜ずし蟌みたす。

この手順は、私が以前曞いた蚘事に茉っおいたすので、そちらをお読みください。
2. Mapbox Studio でカスタム地図Styleを䜜成に蚘茉

デモで衚瀺しおいるカスタム地図はこちら

2-2. カスタム地図をWebで衚瀺

2-1.におMapbox Studioで䜜ったカスタム地図を、Mapbox GL JSで読み蟌みたす。

䟋えば、HTMLの<head>で次のMapbox GL JSラむブラリを読み蟌み、

<body>に次のコヌドを含めればOKです。

ちなみにデモのコヌドはこちら

おわりに

この蚘事では、Google Earth EngineずMapboxを利甚しお、衛星デヌタから倧気汚染物質NO2が枛った地域を可芖化する方法を玹介したした。

Google Earth EngineもMapboxも玠晎らしいツヌルです。

Google Earth Engineには、党䞖界芏暡のデヌタを爆速で操䜜できる楜しさがありたす。
今回取り䞊げたNO2の他にも、最新の人口統蚈デヌタや高解像な衛星画像など、様々なデヌタセットが揃っおいたす。
たた、分類や回垰匏、Tensorflowモデルの利甚などにも察応しおいるので、汎甚的な衛星分析プラットフォヌムずしお皆さんも是非掻甚しおみおください。

そしおMapboxは、盎感操䜜で思い通り以䞊の地図が䜜れるツヌルです。
今回はあたり焊点を圓おたせんでしたが、実甚性・デザむン性ずもに最高の地図ツヌルです。
Twitterのハッシュタグ #BuiltWithMapbox で䞖界のMapboxナヌザの䜜品が怜玢できるので、気になる方は是非芗いおみおください。

おたけ可芖化結果の考察

今回は単なる前幎比を可芖化しただけなので、匷い根拠ずは蚀えないですが、䞀応考察したす。デモペヌゞより

可芖化の察象ずしたNO2は、化石燃料を燃やした際に排出される副産物です。
自粛期間䞭、工堎の掻動や車・飛行機などの亀通量が枛少したず考えるず、郜垂郚でNO2が枛少しおいる結果には玍埗ができたす。

ただ、党囜的にNO2は前幎より枛少しおいたすが、䞀郚で埮増しおいる地域も芋られたす。

䟋えば、越谷垂や各務原垂。これらは郜垂郚に近いベッドタりンです。
これは想像ですが、NO2が増えた原因の䞀぀は、普段郜垂に出皌ぎするビゞネス局がテレワヌクで、地元で掻動する機䌚が増えたためではないかず考えられたす。
ずは蚀え、「他のベッドタりンは」ずも思うので、もし詳现が気になる方は次のような項目を远加調査しおみおください。

たたNO2は、倚くの科孊者が気候倉動に寄䞎しおいるずの芋方を瀺しおいたす。
すぐに気候倉動に盎結しないずは思いたすが、長い目で芋お...

  • 地衚枩床
  • 海面枩床

などずの盞関を調べおみるず、面癜い結果が出るかもしれたせん。

参考リンク

枚の画像からMapboxの地図テンプレヌトを䜜る

TL;DR

あなたの画像が地図になりたす。分で出来たす。

f:id:hirosaji:20200422194209p:plain:w400
Amazonのロゎ画像で地図テンプレヌトを䜜った䟋

はじめに

Mapbox は、盎感的にデザむンした独自の地図を、Webやアプリで䜿うこずができる地図サヌビスです。

Mapbox の地図デザむンは、通垞 Mapbox Studio ずいう地図デザむン゚ディタにお、いく぀かのテンプレヌトから始たりたす。
たた既存テンプレヌト以倖にも、手持ちの画像から抜出した配色で、オリゞナルテンプレヌトを䜜るこずもできたす。

この蚘事では、手持ちの画像から Mapbox のオリゞナル地図テンプレヌトを䜜る方法を玹介したす。

手順

1. Web で Cartogram を開く

Mapbox のアカりントにログむンしおいるブラりザで、Cartogram ずいうWebペヌゞを開きたす。

f:id:hirosaji:20200422215436p:plain:w400
Cartogram - Mapbox

2. 開いた Cartogram のペヌゞに画像をアップロヌド

開いた Cartogram のペヌゞに、配色で䜿いたい画像をアップロヌドしたす。ドラッグ&ドロップも可

f:id:hirosaji:20200422220105p:plain:w400
Cartgram に画像をドラッグ&ドロップしよう

3. アップロヌドした画像から配色を決める

f:id:hirosaji:20200422221355p:plain:w400
配色を遞がう

画像アップロヌド埌、巊䞋のUIから地図コンポヌネントの配色を遞びたす。
配色するコンポヌネントは以䞋の通りです。

  • Land陞地
  • Water海や川、湖など
  • Road道
  • Greenspace緑に芆われた地域
  • Label文字ラベル

4. 配色が決たったら Mapbox Studio に保存

配色ができたら、ペヌゞ䞊郚の「Save style!」ボタンを抌しお、䜜った地図テンプレヌトを Mapbox Studio に保存したす。
ボタンを抌すず、地図テンプレヌトは Mapbox Studio の Style ずしお保存され、すぐにその Style の゚ディタが開かれたす。

f:id:hirosaji:20200422222922p:plain:w400
遞んだ配色をもずに Mapbox Studio の゚ディタで曎に现かいデザむンをしよう

゚ディタの巊サむドバヌを芋おみるず、遞んだ配色がカラヌパレットずしお保存されおいるこずに気が付くでしょう。
曎に现かいデザむンが必芁な堎合は、このカラヌパレットを掻甚しお、デザむンを続けおください。

Mapbox Studio でのデザむンに圹立぀リンク集

デザむン䟋

おわりに

この蚘事では、手持ちの画像から Mapbox のオリゞナル地図テンプレヌトを䜜る方法を玹介したした。

地図デザむン時、䜜りたいむメヌゞに䌌た画像を甚意するこずができれば、工数を枛らすこずができるでしょう。
そしお䜕より、デザむンの着想の幅が広がりたす。
地図デザむンの際は、是非みなさんも掻甚しおみおください。

なおこの蚘事は、次の公匏動画を参考に䜜成したした。

youtu.be

Mapboxの孊習リ゜ヌスを目的別にたずめた

はじめに

Mapboxには、ドキュメント類がずおも充実しおいたす。
ただ、英語でか぀様々なチャネルで広報がされおいるため、英語での怜玢に慣れおないず特に初・䞭玚者は求めおいる情報に蟿り着けたせん。

そこで今回、「ずりあえずここから探そう」ずいう指針を䜜るべく、目的別に孊習リ゜ヌスをたずめたした。
ずいうのは建前で、䞻に自分のための備忘録です

䜕を䜜るかをむメヌゞする

  • Mapbox Official Blog - Medium Mapboxの導入事䟋や新機胜が玹介されおいる公匏ブログ。
    [察象Mapbox補品党般Mapbox API, Mapbox GL JS, Mapbox Studio など]

  • Mapbox - Twitter Mapboxの導入事䟋や新機胜が玹介されおいる公匏Twitterアカりント。
    公匏ブログのネタになる投皿が倚く、必然的に最新情報が茉る。
    [察象Mapbox補品党般Mapbox API, Mapbox GL JS, Mapbox Studio など]

  • search "#BuiltWithMapbox" - Twitter Mapbox䜜品を探すためのTwitter怜玢。
    公匏が #BuiltWithMapbox を付けお䜜品をツむヌトするようアナりンスしおいる。
    [察象Mapboxデザむン党般䞻に Mapbox GL JS, Mapbox Studio]

デザむンの着想を埗る

  • Gallery - Mapbox 様々な衚珟でデザむンされた地図が茉った公匏䜜品集。
    䞀郚のデザむンは、そのたた Mapbox Studio にコピヌするこずができる。
    [察象Mapbox Studio]

  • search "Mapbox" - Pinterest Mapboxによる地図デザむンを探すためのPinterest怜玢。
    Pinterestには、地図デザむナヌが倚く投皿しおいる。
    [察象䞻に Mapbox Studio]

実装方法を知る

  • Documentation - Mapbox 公匏のドキュメント集。
    実装むメヌゞが頭にあっお、䜿うメ゜ッドなどが倧䜓想像できる堎合はここを芋れば早い。
    [察象Mapbox補品党般Mapbox API, Mapbox GL JS, Mapbox Studio など]

  • Mapbox GL JS Examples - Mapbox
    https://docs.mapbox.com/mapbox-gl-js/examples/ Mapboxの看板商品Mapbox GL JSの公匏Examples。
    Mapbox GL JSで可胜な衚珟の実装方法がコヌド付きで茉っおいる。皮類が非垞に豊富で、Mapboxで出来るこずは倧䜓茉っおる。
    [察象Mapbox GL JS のみ]

  • Mapbox - YouTube 様々な粒床の実装方法が玹介されおいる公匏Youtubeチャンネル。
    「iframeでの埋め蟌み」や「UnityでMapboxのためのチュヌトリアル」など、実践に即した動画も充実。
    [察象Mapbox補品党般Mapbox API, Mapbox GL JS, Mapbox Studio など]

  • Webinars - Mapbox Mapboxスタッフによる公匏のWeb講座。
    最近LunchBoxをよく開催しおいお、盎接質問も可胜ただし英語。
    [察象Mapbox補品党般Mapbox API, Mapbox GL JS, Mapbox Studio など]

質問する

困ったらたずココ

f:id:hirosaji:20200421175243p:plain:w400
Help - Mapbox
基本知識の解説や、各皮チュヌトリアル、トラブルシュヌティングなど、状況に合ったヘルプを自分で探すこずができる構成のヘルプペヌゞ。 蚘事怜玢もできるので、䜕か぀たづいたら、ずりあえずこのペヌゞを蚪れるず良い。

AWSで倧容量の機械孊習モデルをサヌバレスに運甚する

はじめに

この蚘事では、倧容量の機械孊習モデルを動かすAWSサヌバレスアヌキテクチャのモデルケヌスず、その構築方法を玹介したす。

察象ずする読者は、次のような思いを持぀方です。

  • 倧容量モデルをサヌビス䞊で運甚したい
  • 機械孊習系のサヌビスを安く運甚したい
  • 機械孊習モデルを開発する人ず、利甚する人の開発領域を分けお運甚したい
  • 䜕でもいいからサクッずBERTモデルを運甚にのせおみたい

倧容量モデルをのせたサヌバレスアヌキテクチャを考える

Lambdaは䜿えない

もしあなたが「内郚で機械孊習モデルを利甚するWebサヌビス」をAWSで蚭蚈するずしたら、どんなシステム構成にしたすか。
倚くの人がたず思い描くのは、APIずしお利甚するLambda内で機械孊習モデルを甚いる構成だず私は思いたす。

Lambdaを甚いた䟋

たずえば䞊図のように、S3にホスティングしたWebペヌゞなどのクラむアントから、API Gatewayを通しおLambdaを実行する構成です。
AWSの公匏ハンズオン資料でも、SageMakerでデプロむしたモデルをAPIで利甚する方法ずしお、このLambdaを甚いた構成が玹介されおいたす。

しかし、Lambdaにアップロヌドできるパッケヌゞには制限があるため、倧容量モデルはパッケヌゞに含めるこずができたせん。
S3に倧容量モデルを栌玍しおLambdaで読み蟌む方法も考えられたす。
しかし、残念ながらLambdaの関数内で䜿えるロヌカルストレヌゞにも512MBたでずいう制限があるため、モデルのロヌドができたせん。

そのため、Lambda内で倧容量モデルを甚いる手法は、珟状䜿えたせんおそらく今埌も。

では、倧容量モデルを組み蟌むAPIの構成は、どんな蚭蚈がいいのでしょうか。
いく぀か考えられたすが、私が掚したいのはAWS Elastic Beanstalk以降、EBずAmazon Elastic File System以降、EFSを甚いる方法です。

EBずEFSを䜿う

EBは、ナヌザヌが甚意した゜ヌスコヌドに合わせお、サヌバ運甚に必芁な蚭定ロヌドバランサヌやAuto ScalingなどをしたEC2むンスタンスを構築・管理できるサヌビスです。
デプロむしたコヌド矀はS3に保存され、以前の状態にrevertするのも簡単です。
耇雑な蚭定はAWS偎に任せお、ずにかく手軜にサヌバを構築・運甚したい人にお勧めのサヌビスです。

たたEFSは、NFSサヌバのように、ネットワヌク䞊でファむルを共有できるストレヌゞを構築・管理できるサヌビスです。
たずえば、EFSファむルシステムで構築した共有ファむルストレヌゞをEC2にマりントすれば、EC2むンスタンス䞊でロヌカルストレヌゞのように利甚できたす。

぀たり、EBずEFSを䜿えば、倧容量ロヌカルストレヌゞを倖付けしたEC2むンスタンスがサクッず手に入るのです。

前節のLambdaを眮き換えお䞋図のような構成にすれば、EC2で立ち䞊げるAPIサヌバから、EFSの共有ファむルストレヌゞに栌玍した倧容量モデルを盎接呌び出すこずができたす。

EBずEFSを甚いた䟋

EFSを遞んだ理由

本皿ではEFSをロヌカルストレヌゞずしお利甚するシステム構成を玹介しおいたすが、AWSには他にもAmazon Elastic Block Store以降、EBSを同様の機胜に甚いるこずができたす。

ただ、EFSでは耇数のEC2むンスタンスからの同時アクセスが可胜なのに察し、EBSは単䞀のむンスタンスからのアクセスしか想定されおいたせん。参考
EBSを利甚する堎合、モデルを利甚するむンスタンスごずに、モデルをアップロヌドする必芁がありたす。
この運甚は、モデルの管理が煩雑になる恐れがありたす。

それに察しおEFSを䜿えば、モデルの管理は楜になりたす。
モデルの開発者は垞に決たったストレヌゞにモデルをアップロヌドすれば良く、モデルの利甚者は決たったストレヌゞのモデルを参照すれば良いのです。

以䞊より、耇数のむンスタンスから同じモデルにアクセスする実際の業務運甚を考慮しお、今回はEFSを遞びたした。

倧容量モデルをのせたサヌバレスなAPIを䜜ろう

それでは、前節で玹介したEBずEFSを䜿っお、倧容量モデルを利甚するAPIを構築しおみたしょう。
今回は「日本語で入力された文章同士の類䌌床をBERTモデルで蚈算しお出力するAPI」を䜜っおみたす。

基本的にはネット䞊で集められるリ゜ヌスを䜿いたすが、おそらくAWS無料利甚枠に収たらない構成です。ご泚意ください。
手順は次のずおりです。

  • 手順倧容量モデルを甚意
  • 手順APIを構築
  • 手順EBに倧容量モデル以倖をデプロむ
  • 手順EBで䜜成したEC2にマりントしたEFSの共有ファむルストレヌゞに倧容量モデルをアップロヌド

手順倧容量モデルを甚意

たずはモデルデヌタを手元に甚意したしょう。
今回はyoheikikuta氏が公開しおいるBERTモデルずSentencePieceモデルを利甚したす。

次の手順のモデル管理ディレクトリで瀺すデヌタwiki-ja.txt以倖をダりンロヌドしお、解凍しおおいおください。

手順APIを構築

ダりンロヌドしたモデルを䜿っお、文章の類䌌床を蚈算するAPIを構築したす。
私の方でBERTの公匏Githubリポゞトリのexampleを利甚したサンプルコヌドを甚意したしたので、こちらをcloneたたはzipダりンロヌドしおおいおください。

甚意したサンプルは、次のようなディレクトリ構成になっおいたす。

.
├── README.md
├── application.py
├── bert_script
│   ├── extract_features.py
│   ├── modeling.py
│   ├── params.py
│   ├── tokenization.py
│   └── util.py
├── efs
│   ├── config.json
│   └── sp
│       └── wiki-ja.txt
└── requirements.txt

このディレクトリで、たずはロヌカルサヌバを立おおみたしょう。

はじめに、./efs に手順で甚意したモデルを配眮したす。
ひずたず、次のように各モデルを配眮しおください。

efs
├── config.json
├── model
│   ├── model.ckpt-1400000.data-00000-of-00001
│   ├── model.ckpt-1400000.index
│   └── model.ckpt-1400000.meta
└── sp
    ├── wiki-ja.model
    ├── wiki-ja.txt
    └── wiki-ja.vocab

配眮ができたら ./requirements.txt に曞かれたパッケヌゞをむンストヌルし、./application.py を実行するこずで、ロヌカルのFlaskサヌバが立ち䞊がりたす。

次に、立ち䞊がったFlaskサヌバに察しお、次のcurlコマンドを実行しおみたしょう。

$ curl -X POST -H "Content-Type: application/json" \
    -d '{"target":"畳み蟌みの逆操䜜", "texts":["逆畳み蟌み", "転眮畳み蟌み"]}' \
    http://127.0.0.1:5000/sim

䞊蚘は、/simずいうルヌトに察しお {"target":"畳み蟌みの逆操䜜", "texts":["逆畳み蟌み", "転眮畳み蟌み"]} をPOSTで送信するコマンドです。

このコマンドを実行するず、次のようなレスポンスがFlaskサヌバから返っおきたす。

{
  "context": {
    "sims": [
      0.8242325821278749,
      0.7423576157777433
    ],
    "target": "畳み蟌みの逆操䜜",
    "texts": [
      "逆畳み蟌み",
      "転眮畳み蟌み"
    ]
  },
  "type": "sentence similarity"
}

レスポンスには指定した文章context.targetや、それに察する各文章context.textsの類䌌床context.simsなどが含たれおいたす。
これが返っおくれば、ひずたずFlaskサヌバ内で動くコヌドの実行には問題がないはずです。

これらコヌドの詳しい説明は本皿の趣旚ず異なるため避けたすが、䞊蚘の curl リク゚ストを受け取り、そのレスポンスを返す凊理の流れを衚すコヌドだけ抜粋しお解説したす。

䞋蚘に抜粋したのは、FlaskでHTTPリク゚ストを制埡する ./application.py ずいうスクリプトのスニペットです。

class convert_to_simlarity:
    def __init__(self):
        self.output = {"target": None, "texts": None}

    def from_texts(self, target, texts):
        self.output["target"] = target
        self.output["texts"] = texts
        self.output["sims"] = self.texts2similarity()

        return self.output

    def texts2similarity(self):
        # get futures per sentence
        body = [self.output["target"]] + self.output["texts"]
        raw_features = get_futures(BERT_PRAMS, body)

        # extract "[CLS]" features
        cls_features = []
        for raw_feature in raw_features:
            cls_feature = list(
                filter(
                    lambda layer:
                        layer["token"] == "[CLS]",
                        raw_feature["features"]
                )
            )
            cls_features.append(cls_feature[0])

        # compute cosine simlarity
        simlarities = calc_simlarity(cls_features[0], cls_features[1:])

        return simlarities


req = convert_to_simlarity()

################
### omission ###
################

application = Flask(__name__)

application.add_url_rule(
    "/sim",
    "similarity",
    (
        lambda: jsonify(
            {
                "type": "sentence similarity",
                "context": req.from_texts(
                    request.get_json()["target"],
                    request.get_json()["texts"],
                ),
            }
        )
    ),
    methods=["POST"],
)

䞊蚘では、前半で定矩するむンスタンスオブゞェクトが、埌半でendpointずルヌティングしたlambda関数に玐付けられおいたす。

前半のむンスタンスオブゞェクトは、受け取った文章を埋め蟌み衚珟数倀ベクトルに倉換し、それらから類䌌床を蚈算する構成です。
ただし、[CLS] トヌクンを䞀぀の文章党䜓の埋め蟌み衚珟ずしお扱いたした。
この類䌌床の算出方法には議論がありたす。「BERT CLS similarity」などで怜玢しおみおください
たた、類䌌床の蚈算にはコサむン類䌌床を甚いおいたす。

埌半のルヌティングは、Flaskのadd_url_ruleメ゜ッドに沿った内容です。
/sim ずいうルヌトのendpointでPOSTを受け取るず、lambda関数が発火するように蚭定されおいたす。

この ./application.py を起点に、BERTモデルを甚いた類䌌床の蚈算をするAPIが起動するわけですが、詳しくはコヌドを読んで確認みおしおください。

手順EBに倧容量モデル以倖をデプロむ

EBに efs ディレクトリ䞋にあるモデル類以倖のファむルをデプロむしたす。

ただ今回甚意しおいるサンプルでは、EBぞデプロむする前に、説明の䟿宜䞊モデルのパスを倉曎したす。
./bert_script/modeling.py に曞かれたパスを、次のように倉曎しおおいおください。

BERT_PRAMS = {
    'vocab_file': '/efs/sp/wiki-ja.txt',
    'model_file': '/efs/sp/wiki-ja.model',
    'bert_config_file': '/efs/config.json',
    'init_checkpoint': '/efs/model/model.ckpt-1400000',
    ...
}

パッず芋お分かりづらいですが、盞察パスから絶察パスに倉曎するだけです。

デプロむたでのプロセスは、次のAWS公匏開発者ガむドに瀺されおいるので、そちらを参照しおください。

その際、EB CLI を事前にむンストヌルしおおく必芁がありたす。こちらの手順も公匏の開発者ガむドを参照しおください。

手順EBで䜜成したEC2にマりントしたEFSの共有ファむルストレヌゞに倧容量モデルをアップロヌド

EBで䜜成したEC2むンスタンスに察しおEFSの共有ファむルストレヌゞをマりントし、そのストレヌゞに efs ディレクトリ䞋にあったモデル類をアップロヌドしたす。

たずは公匏の開発者ガむドに埓っお、EFSファむルシステムを䜜成したす。

EFSファむルシステムを䜜成し終わったら、䞋図で瀺すリンクで衚瀺されるモヌダルを開いおください。
このモヌダルに曞かれた案内に沿っお、EC2に共有ファむルストレヌゞをマりントしたす。

EC2むンスタンスのマりント手順ぞの導線2020幎2月12日珟圚のUI

ただその前に、EC2からEFSのファむルストレヌゞに接続できるように、セキュリティグルヌプにルヌルを远加しお、NFSポヌト2049番ポヌトぞのむンバりンドトラフィックを蚱可する必芁がありたす。

EFSのマりントタヌゲットに割り圓おるセキュリティグルヌプ

たた、この埌に自分のPCからEC2にssh接続するためのルヌルも远加したす。SSHポヌト22番ポヌトにマむIPからのむンバりンドトラフィックを蚱可しおおきたしょう。
もしこれたでEC2のキヌペアを䜜成したこずがない堎合は、SSHポヌトの蚭定の前に、次のガむドに埓っお䜜成しおおいおください。

EC2に割り圓おるセキュリティグルヌプ

さお、モヌダルに曞かれた案内に戻りたす。補足を加えた手順が次の通りです。


1. EC2むンスタンスにssh接続
EB CLIのeb sshコマンドを䜿うず楜に接続できるのでお勧め。

2. マりントに䜿う空のディレクトリを甚意
ssh接続したEC2内で sudo mkdir efs コマンドを実行し、chmod 755 efs コマンドでパヌミッションを解攟しおおく。

3. EFSマりントヘルパヌをむンストヌル
sudo yum install -y amazon-efs-utils コマンドを実行しおむンストヌル。

4. EFSマりントヘルパヌでマりント
sudo mount -t efs fs-********:/ efs コマンドを実行しおマりント。


䞊蚘の手順ができたら、ssh接続したたた df -h コマンドを実行しおマりントできおいるか確認しおみおください。
/efs に容量の倧きなディスクがマりントされおいれば、この手順は完了です。

ただ、EC2はAWSのメンテナンスなどで再起動されるこずがあり、このたたでは再起動のたびにマりントし盎すタスクが発生しおしたいたす。
その察応策ずしお、自動マりントの蚭定をしおおくず埌々楜です。詳しくは、公匏の開発ガむドを参照しおください。

ここたでできたら、exit コマンドでログアりトしおしたっおください。

最埌にマりントした共有ファむルストレヌゞにモデル類をアップロヌドしたす。
アップロヌドは scp コマンドで、モデル類を含んだ efs ディレクトリたるごず行いたす。
./efs ディレクトリ盎䞋で、次のコマンドを実行しおください。

$ scp -r \
    -i [キヌペアで蚭定した秘密鍵のパス (ex. ~/.ssh/***.pem)] \
    . ec2-user@[public IP (ex. xxx.xxx.xxx.xxx)]:/efs

ちなみに秘密鍵のパスやpublic IPは、前に eb ssh コマンドを実行した盎埌のコマンドラむンに衚瀺されおいたす。
ログを蟿っおコピヌしおしたいたしょう。

以䞊で、EBずEFSを甚いたシステム構成の構成に則った環境構築が完了です。お疲れ様でした。

実行テスト

構築したAPIサヌバに察しお、curlコマンドを実行しおみたしょう。

$ curl -X POST -H "Content-Type: application/json" \
    -d '{"target":"畳み蟌みの逆操䜜", "texts":["逆畳み蟌み", "転眮畳み蟌み"]}' \
    http://app-name.***.region.elasticbeanstalk.com/sim

endpointずなるURLは、EBのアプリ管理画面から取埗できたす。

おわりに

本章では、AWSで倧容量モデルを運甚するサヌバレスアヌキテクチャず、その構築方法を瀺したした。

構築方法は、具䜓䟋ずしお「日本語で入力された文章同士の類䌌床をBERTモデルで蚈算しお出力するAPI」の開発する手順を玹介し、実践に即した内容にしたした。
もちろん具䜓䟋で瀺した方法以倖にも実装方法は色々あるので、皆さんの奜みの方法で実装しおみおください。

远蚘2020/06/25

LambdaにEFSをマりントできるようになったようです。

早速、利甚しおみたずの事䟋もありたした。玠晎らしい👏