0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

POIから作る地域特徴量&Embedding入門:街を数値化して分かることと限界

0
Last updated at Posted at 2026-10-20

前回は、Foursquare、Overture、OpenStreetMapのPOIデータを比較しました。今回はその続きとして、公開POI(お店や施設などの地点)から街を数値化し、似た街の検索、クラスタリング、地域Embeddingまで試します。

先に結論を書くと、POIから地域を比較する仕組みは作れます。ただし、得られるのは「指定した条件から見た街の一側面」であり、街そのものの性格ではありません。

POIから似た街を探すまでの流れ

1地域を1行の表にする

最初に作るのが「地域特徴量」です。これは、複数の地域を同じ物差しで比べるための数値プロフィールです。

今回は東京都内656駅について、駅の代表点を中心とする1km四方を集計しました。保存する表は地域ID、面積、件数なども含む15列で、そのうち比較に使ったのは次の8項目です。

  • POI登録密度
  • 食事、カフェ、バー、衣料、美容、食品小売の構成比
  • 250m格子で見たPOIの局所集中度(最も密集した格子が地域平均の何倍か)

POIから1地域1行の地域特徴量を作る流れ

吉祥寺駅周辺の地域特徴量プロフィール

実装のポイントは、範囲内のPOIを数え、どの地域にも同じ列を用意することです。次のコードは、計算部分だけを抜き出しています。

count = len(places)
density = count / area_km2
category_counts = places["display_group"].value_counts()

profile = {
    "region_id": region_id,
    "poi_density_per_km2": density,
    **{
        f"{name}_share": category_counts.get(name, 0) / count
        for name in category_groups
    },
    "peak_to_mean_density_250m": peak_density / density,
}

この表では、1行が1地域、1列が1つの特徴です。これで地域同士を同じ形の数値で比べられます。

この地域データは、似た街を探したり、街をグループに分けたり、細かなカテゴリを圧縮したりするのに使います。

類似検索・クラスタリング・Embeddingの役割

数値の距離から「似た街」を探す

列ごとに単位とばらつきが違うため、密度と集中度へlog1p(極端に大きい値の影響を抑える対数変換)を適用し、中央値と四分位範囲(データ中央50%の幅)で数値をそろえました。6つのカテゴリ比率は、その部分だけが距離を支配しないよう重みも調整しています。

values[["density", "concentration"]] = np.log1p(
    values[["density", "concentration"]]
)
z = (values - values.median()) / (
    values.quantile(0.75) - values.quantile(0.25)
)
z[category_columns] /= np.sqrt(6)

distance = np.linalg.norm(z - z.loc["kichijoji"], axis=1)

この8特徴量で吉祥寺に近かったのは、町田、自由が丘、立川南などでした。

吉祥寺に近い地域特徴量を持つ上位10駅

ここでの距離は類似率や正解率ではありません。「今回選んだ8項目が近い順」です。特徴量や重みを変えれば順位も変わります。

基準の街を決めずに分類する

同じ8特徴量をK-means(近いデータ同士を指定した数のグループに分ける手法)へ入力すると、656駅周辺を大きく3群へ整理できました。吉祥寺は「高密度・飲食集積型」と仮称した群に入りました。

東京都内656駅周辺をK-meansで3群に分類した結果

ただし、「東京の街は本当に3種類ある」という意味ではありません。3~8群を比較しても評価指標ごとの最良値は一致せず、3群は規模、安定性、説明しやすさから選んだ粗い整理です。

961カテゴリを64次元へ圧縮する

8特徴量では、ATM、駐車場、事業所などを「その他」にまとめています。そこで次は、961カテゴリの件数をTF-IDF(多くの地域にあるカテゴリの重みを下げる方法)で重み付けし、TruncatedSVD(情報をなるべく残しながら列数を減らす線形手法)で64次元(64列の数値)へ圧縮しました。Embeddingとは、対象を比較や検索に使える固定長の数値ベクトルで表すことです。今回はLLMではなく、線形の次元圧縮で作ったものを「地域Embedding」と呼びます。

8特徴量・961カテゴリ・64次元Embeddingの比較

from sklearn.decomposition import TruncatedSVD
from sklearn.feature_extraction.text import TfidfTransformer
from sklearn.preprocessing import normalize

tfidf = TfidfTransformer(
    norm="l2", smooth_idf=True, sublinear_tf=False
).fit_transform(category_counts)

embedding = TruncatedSVD(
    n_components=64, n_iter=10, random_state=42
).fit_transform(tfidf)
embedding = normalize(embedding)

8特徴量、961カテゴリ、64次元Embeddingで、吉祥寺の上位10駅に共通したのは5駅でした。Embeddingでは中目黒や学芸大学などが上位へ入りました。

表現を細かくしたことで見える違いは増えましたが、Embeddingにしたから改善したとは言えません。 POIを半分ずつに分けた近傍一致率(上位候補がどれだけ共通したか)は、圧縮前の30.2%に対してEmbeddingは26.8%でした。また、「街の類似」に正解ラベル(正解として比較できる基準データ)がないため、どちらが正しいかも自動では判定できません。

いちばん注意したいのは「どこまでを街とするか」

駅から東西南北500mの範囲を800mへ広げると、3方式すべてで似た駅の順位が変わりました。500m時点の上位10駅のうち、800mでも残った平均駅数は次のとおりです。

表現 上位10に残った平均駅数
A:8特徴量 2.24駅
B:961カテゴリ 3.31駅
C:64次元Embedding 3.19駅

分析範囲は結果を左右する分析条件

駅の東側が商業地、西側が住宅地なら、範囲を広げる方向や形でも集計結果は変わります。地理空間分析では、集計区域の大きさや分け方で結果が変わる問題をMAUP(Modifiable Areal Unit Problem)と呼びます。

これは分析が無意味という話ではありません。「街の性格」を漠然と求めるのではなく、用途から範囲を決める必要があるということです。

避けたい問い 比較しやすい問い
この駅はどんな性格か 駅の各出口から徒歩5分で行けるカフェ構成は似ているか
住みやすい街はどこか 徒歩10分圏にある生活施設の構成は似ているか
東京の街を正しく分類したい 指定したPOIと範囲で大まかにグループを眺めたい

まとめ

  • 地域特徴量は、街を同じ列で比較するための数値プロフィール
  • 類似検索とクラスタリングは、選んだ特徴から候補やまとまりを探す方法
  • Embeddingは表現を変える方法であり、自動的に精度を上げる魔法ではない
  • データ、特徴量、重み、分析範囲を変えると結果も変わる
  • 「誰が、どこから、何を利用するか」を先に決めると、範囲と結果を説明しやすい

今回の一連の実験では、POIから街を数値化する方法だけでなく、その数値をどこまで信頼できるかも確認できました。地域ベクトルは街の本質ではなく、条件を決めて使う比較の道具と考えるのがよさそうです。

動画で見る

本文の前半と後半を図解した動画も用意しました。必要なところから見られます。

前編:地域特徴量と類似検索

後編:クラスタリング、地域Embedding、分析範囲の限界

個人ブログの詳しい解説

各実験の条件、図表、結果、注意点は、個人ブログで詳しく説明しています。

  1. POIデータから作る「地域特徴量」 Pythonで吉祥寺駅周辺を数値化してみた
  2. 「吉祥寺」に似た街はどこ? POIデータで東京都内656駅周辺を比べてみた
  3. POIデータで街をクラスタリング Pythonで東京都内656駅周辺を分類してみた
  4. 街をベクトルで表すと何が変わる? Pythonで地域Embeddingを試してみた
  5. POIで街を数値化して分かったこと 分析範囲で「似た街」はどう変わる?

コードと詳しい検証記録

使用したPOIはOverture Maps FoundationのOverture Places release(データ版)2026-09-23.0です。駅には国土交通省「国土数値情報(鉄道データ)N02-25」を加工して使用しました。POIは登録情報であり、実際の営業中店舗数、人流、売上、街の人気、住みやすさを表すものではありません。

※本記事は個人の見解であり、所属組織を代表するものではありません。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?