์š”์•ฝ

  • BallTree๋Š” ์œ ํด๋ฆฌ๋“œ ๊ฑฐ๋ฆฌ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ๋ฐ์ดํ„ฐ ๊ณต๊ฐ„์„ ๊ตฌ์ฒด(Ball)๋กœ ๊ฐ์‹ธ ๊ณ„์ธต์ ์ธ ์ด์ง„ ํŠธ๋ฆฌ๋ฅผ ๊ตฌ์„ฑํ•˜๋Š” ์ตœ๊ทผ์ ‘ ์ด์›ƒ ํƒ์ƒ‰ ์•Œ๊ณ ๋ฆฌ์ฆ˜์ž„.
  • ๋‹จ์ˆœ ๊ฑฐ๋ฆฌ ๊ณ„์‚ฐ ๋ฐฉ์‹๊ณผ ๋‹ฌ๋ฆฌ ํƒ์ƒ‰ ๊ณผ์ •์—์„œ ๋ถˆํ•„์š”ํ•œ ์ž์‹ ๋…ธ๋“œ๋“ค์„ ํšจ์œจ์ ์œผ๋กœ ์ œ๊ฑฐํ•˜์—ฌ ๋ฐ์ดํ„ฐ๊ฐ€ ๋งŽ์•„์งˆ์ˆ˜๋ก ๊ณ„์‚ฐ๋Ÿ‰์„ ํš๊ธฐ์ ์œผ๋กœ ์ค„์—ฌ์คŒ.
  • KD-Tree์— ๋น„ํ•ด ์ดˆ๊ธฐ ํŠธ๋ฆฌ ๊ตฌ์ถ• ๋น„์šฉ์€ ๋” ๋“ค์ง€๋งŒ, ์ฐจ์ˆ˜๊ฐ€ ์ปค์งˆ์ˆ˜๋ก ๋ฐ์ดํ„ฐ๋ฅผ ํ›จ์”ฌ ๋น ๋ฅด๊ฒŒ ํƒ์ƒ‰ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์žฅ์ ์ด ์žˆ์Œ.
  • ์•Œ๊ณ ๋ฆฌ์ฆ˜์€ ๊ฐ€์žฅ ๊ฑฐ๋ฆฌ๊ฐ€ ๋จผ ํฌ์ธํŠธ๋“ค์„ ๊ธฐ์ค€์œผ๋กœ ์žฌ๊ท€์ ์œผ๋กœ ํ•˜์œ„ Ball์„ ์ƒ์„ฑํ•˜๊ณ , ํƒ์ƒ‰ ์‹œ์—๋Š” ์ƒ์œ„ Ball์—์„œ ๋ฆฌํ”„ ๋…ธ๋“œ๊นŒ์ง€ ์ขํ˜€๊ฐ€๋Š” ๋ฐฉ์‹์„ ์‚ฌ์šฉํ•จ.
  • ํŒŒ์ด์ฌ์˜ sklearn ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ํ†ตํ•ด ์‰ฝ๊ฒŒ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ํŠน์ • ๋ฐ˜๊ฒฝ ๋‚ด์˜ ๊ฒฉ์ž ๋ฐ์ดํ„ฐ๋ฅผ ์ถ”์ถœํ•˜๋Š” ๋“ฑ ๊ณต๊ฐ„ ๋ฐ์ดํ„ฐ ๋ถ„์„์— ์œ ์šฉํ•˜๊ฒŒ ํ™œ์šฉ๋จ.

1. ๊ฐœ์š”

1.1 BallTree ์•Œ๊ณ ๋ฆฌ์ฆ˜์ด๋ž€?

์ตœ๊ทผ์ ‘ ์ด์›ƒ ํƒ์ƒ‰(knn search)๊ณผ ์œ ์‚ฌํ•˜๋ฉฐ, ํŠน์ • ๋ฐ์ดํ„ฐ๋ฅผ ํƒ์ƒ‰ํ•˜๋Š” tree ๊ตฌ์กฐ ์•Œ๊ณ ๋ฆฌ์ฆ˜

๋ชฉ์ : ์œ ํด๋ฆฌ๋“œ ๊ฑฐ๋ฆฌ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ๋น ๋ฅด๊ฒŒ ์ตœ๊ทผ์ ‘ ์ด์›ƒ์„ ํƒ์ƒ‰ ํ•ต์‹ฌ ๋‚ด์šฉ: ๋ฐ์ดํ„ฐ ๊ณต๊ฐ„์„ Ball๋กœ ๊ฐ์‹ธ๋Š” ๋ฐฉ์‹์ธ ์ด์ง„ ํŠธ๋ฆฌ๋ฅผ ๊ตฌ์„ฑ ์ฃผ์š” ์šฉ๋„: KNN, ์œ ์‚ฌ๋„ ๊ฒ€์ƒ‰, ๊ณ ์ฐจ์› ๊ฑฐ๋ฆฌ ๊ณ„์‚ฐ

1.2 ์ฃผ์š” ์šฉ์–ด

์šฉ์–ด์˜๋ฏธ
Ball์ค‘์‹ฌ์  ์™€ ์„ ๊ฐ€์ง€๋Š” ๊ตฌ์ฒด(๋ฐ์ดํ„ฐ ํฌ์ธํŠธ๋Š” ํ•ด๋‹น Ball์— ์กด์žฌ)
Leaf Node์‹ค์ œ ๋ฐ์ดํ„ฐ ํฌ์ธํŠธ๋“ค์ด ์ €์žฅ๋œ ํ•˜์œ„ ๋…ธ๋“œ
Internal Node๋‘ ๊ฐœ์˜ ์ž์‹ Ball์„ ๊ฐ–๋Š” ๋…ธ๋“œ
TreeBall๋“ค์ด ๊ฒŒ์ธต์ ์œผ๋กœ ๊ตฌ์„ฑ๋œ ์ด์ง„ ํŠธ๋ฆฌ ๊ตฌ์กฐ

2. ํŠน์ง•

BallTree๋Š” KD-Tree์™€ ๋น„๊ตํ•˜์—ฌ, ์ดˆ๊ธฐ ํŠธ๋ฆฌ ๊ตฌ์„ฑ ๋น„์šฉ์ด ํฌ์ง€๋งŒ ์ฐจ์ˆ˜๊ฐ€ ์ปค์งˆ์ˆ˜๋ก ๋ฐ์ดํ„ฐ๋ฅผ ํ›จ์”ฌ ๋น ๋ฅด๊ฒŒ ํƒ์ƒ‰ํ•  ์ˆ˜ ์žˆ๋Š” ์žฅ์ ์ด ์žˆ๋‹ค.

๋ฐ˜๋ฉด์—, BallTree ๋Š” kd tree ๋ณด๋‹ค ํ›จ์”ฌ ๋น ๋ฅด๊ฒŒ ๊ฒฐ๊ณผ๋ฅผ ๋„์ถœํ•œ๋‹ค.

๋น„๊ต: BallTree vs ๋‹จ์ˆœ ๊ฑฐ๋ฆฌ ๊ณ„์‚ฐ

  • ๋‹จ์ˆœ ๊ฑฐ๋ฆฌ ๊ณ„์‚ฐ: ๋ฐ์ดํ„ฐ ์ˆ˜ ์ฆ๊ฐ€ํ• ์ˆ˜๋ก ๊ณ„์‚ฐ๋Ÿ‰ ๊ธฐํ•˜๊ธ‰์ˆ˜์  ์ฆ๊ฐ€
  • BallTree: ํŠธ๋ฆฌ ๊ตฌ์กฐ ์ƒ์„ฑ์„ ํ†ตํ•ด, ํŠน์ • ๋…ธ๋“œ๊ฐ€ ์งˆ์˜ํ•œ ๊ฑฐ๋ฆฌ๋ณด๋‹ค ํฌ๋ฉด ํ•ด๋‹น ๋…ธ๋“œ์˜ ์ž์‹ ๋…ธ๋“œ๋“ค์€ ๋ชจ๋‘ ๋ฒ„๋ฆผ โ‡’ ๊ณ„์‚ฐ๋Ÿ‰ ๊ฐ์†Œ!

3. ์•Œ๊ณ ๋ฆฌ์ฆ˜

๋ชฉ์ : Input Data์™€ ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด Point ํƒ์ƒ‰

  1. ๋žœ๋คํ•œ point ์„ ํƒํ•˜๋Š” ๊ณผ์ •์„ ์žฌ๊ท€์ ์œผ๋กœ ์ˆ˜ํ–‰ํ•˜์—ฌ Ball ์ƒ์„ฑ
  2. Ball ๊ธฐ๋ฐ˜ Tree ๊ตฌ์„ฑ
  3. Input data๊ฐ€ ์†ํ•œ Ball์„ ์ฐพ๋Š” ํŠธ๋ฆฌ ๋…ธ๋“œ ํƒ์ƒ‰ํ•˜์—ฌ ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด Ball ํƒ์ƒ‰
  4. ํ•ด๋‹น Ball ์— ์žˆ๋Š” Point ์ค‘ ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด Point ํƒ์ƒ‰

3.1 Ball ์ƒ์„ฑ

๋žœ๋คํ•œ Point P1 ์„ ํƒํ•œ ํ›„, ๊ฐ€์žฅ ๊ฑฐ๋ฆฌ๊ฐ€ ๋จผ ํฌ์ธํŠธ P2 ์™€ P2์—์„œ ๊ฐ€์žฅ ๊ฑฐ๋ฆฌ๊ฐ€ ๋จผ ํฌ์ธํŠธ P3 ์„ ํƒ

P2์™€ P3๋ฅผ ์žˆ๋Š” ์„ ์„ ์ƒ์„ฑํ•˜์—ฌ ํ•ด๋‹น ์„ ์— ์ค‘๊ฐ„์ ์„ ๊ธฐ์ค€์œผ๋กœ ์„ ์„ ๋‚˜๋ˆ” โ‡’ l1, l2

๋‹ค๋ฅธ Point๋“ค์„ ๋‚˜๋ˆ„์–ด์ง„ ๊ฐ ์„ ์— ์ˆ˜์„ ์˜ ๋ฐœ์„ ๋‚ด๋ฆผ(=projection), ๊ฐ ์„ ๋“ค์— ํˆฌ์˜๋œ ์ ๋“ค์˜ ์ถ• ์„ฑ๋ถ„์— ํ•ฉ์˜ ํ‰๊ท ์„ ์ƒˆ๋กœ์šด Ball์˜ ์ค‘์‹ฌ์ ์œผ๋กœ ๊ฐ๊ฐ ์ƒ์„ฑ (๋‹จ, ์—ฌ๊ธฐ์„œ P1์€ ์ œ์™ธ๋œ๋‹ค. ์™œ๋ƒํ•˜๋ฉด ์ด๋ฏธ P1์„ ์ค‘์‹ฌ์œผ๋กœ ๋ชจ๋“  ์ ์„ ํฌํ•จํ•˜๋Š” Ball1์„ ๋งŒ๋“ค์—ˆ๊ธฐ ๋•Œ๋ฌธ์— ํ•˜์œ„ Ball ์ƒ์„ฑ ์‹œ์—๋Š” ์ œ์™ธ๋œ๋‹ค.)

๊ฐ๊ฐ ์ƒˆ๋กญ๊ฒŒ ์ƒ์„ฑ๋œ Ball์˜ ์ค‘์‹ฌ์ ์—์„œ ์ค‘์‹ฌ์  ์ƒ์„ฑ์— ํ™œ์šฉ๋œ ๊ธฐ์กด Point ์ค‘ ๊ฐ€์žฅ ๊ฑฐ๋ฆฌ๊ฐ€ ๋จผ Point์™€์˜ ๊ฑฐ๋ฆฌ๋ฅผ ๋ฐ˜์ง€๋ฆ„์œผ๋กœ ํ•˜๋Š” Ball ์„ ์ƒ์„ฑ

3.2 Tree ๊ตฌ์„ฑ

์œ„ ๊ณผ์ •์„ ์žฌ๊ท€์ ์œผ๋กœ ๋ฐ˜๋ณตํ•˜์—ฌ ์ตœ์ข… Ball์„ ์ƒ์„ฑํ•œ๋‹ค.

Ball์˜ ์œ„๊ณ„ ๊ตฌ์กฐ์— ๋งž๊ฒŒ Tree๋ฅผ ๊ตฌ์„ฑํ•œ๋‹ค.

3.3 Ball ํƒ์ƒ‰

ํŠธ๋ฆฌ ๋…ธ๋“œ ํƒ์ƒ‰์„ ํ†ตํ•ด Input Data(8,5)๊ฐ€ ์†ํ•œ Ball์„ ์ฐพ์œผ๋ฉฐ, ๋‹จ๊ณ„์ ์œผ๋กœ ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด Ball ์„ ์„ ํƒ B1 - B3 - B6

3.4 ์ตœ๊ทผ์ ‘ Point ํƒ์ƒ‰

์ตœ์ข… Ball(B6) ๋‚ด Point๋“ค ๊ณผ์˜ ์œ ํด๋ฆฌ๋“œ ๊ฑฐ๋ฆฌ๋ฅผ ์‚ฐ์ถœํ•œ ํ›„, ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด Point(8,3) ์„ ํƒ


4. Python ์ฝ”๋“œ ์˜ˆ์‹œ

๊ฒฉ์ž ๋ฐ์ดํ„ฐ ํ™œ์šฉํ•˜์—ฌ, ๊ฐ ๊ฒฉ์ž๋ณ„ ๋ฐ˜๊ฒฝ ๋‚ด ์†ํ•œ ๊ฒฉ์ž ๋ชฉ๋ก ์‚ฐ์ถœ

from skleran.neighbors import BallTree

๋ชฉ์ : ๊ฐ ๊ฒฉ์ž ์ค‘์‹ฌ์ ์„ ๊ธฐ์ค€์œผ๋กœ ํŠน์ • ๋ฐ˜๊ฒฝ ๋‚ด ์œ„์น˜ํ•œ ๊ฒฉ์ž ์ค‘์‹ฌ์ ์— ํ•ด๋‹นํ•˜๋Š” ๊ฒฉ์ž ๋ชฉ๋ก ์ถ”์ถœ

๋‹จ๊ณ„ ๊ตฌ์„ฑ

  1. ๊ฐ ๊ฒฉ์ž๋ณ„ ์ค‘์‹ฌ์ขŒํ‘œ ์ƒ์„ฑ
    1. geometry์ •๋ณด๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ, centroid ๋ฉ”์„œ๋“œ ํ™œ์šฉ
    2. geometry์ •๋ณด๊ฐ€ ์—†๊ณ  ์œ„๊ฒฝ๋„ ์ •๋ณด๋งŒ ์žˆ๋Š” ๊ฒฝ์šฐ, ์ขŒํ‘œ๊ฐ’ array ํ˜•ํƒœ ์ƒ์„ฑ(N, 2)
  2. ์ค‘์‹ฌ์  ๊ธฐ์ค€ BallTree ์ดˆ๊ธฐ ์ƒ์„ฑ
  3. ํŠน์ • ๋ฐ˜๊ฒฝ ๋‚ด ์ธ๋ฑ์Šค ์ถ”์ถœ
    1. tree.query_radius(X, r, return_distance = False, count_only = False, sort_result = False) ํ™œ์šฉ
      1. X: ์ขŒํ‘œ๊ฐ’ array
      2. r: ๋ฐ˜๊ฒฝ(m)
      3. return_distance: ๊ฑฐ๋ฆฌ ๊ฐ’ ๋ฐ˜ํ™˜ ์—ฌ๋ถ€
      4. count_only: ๋ฐ˜๊ฒฝ ๋งŒ์กฑ ๊ฑด์ˆ˜๋งŒ ๊ฐ€์ ธ์˜ค๋Š”์ง€
      5. sort_result: ๊ฑฐ๋ฆฌ์™€ ์ธ๋ฑ์Šค ๊ธฐ์ค€ ์ •๋ ฌ
from sklearn.neighbors import BallTree
import numpy as np
 
# 1. ๊ฐ ๊ฒฉ์ž๋ณ„ ์ค‘์‹ฌ์ขŒํ‘œ ์ƒ์„ฑ
coords = np.array([(geom.centroid.x, geom.centroid.y) for geom in gdf.geometry]) ## geometry ์กด์žฌ
coords = np.vstack([gdf['x'].values, gdf['y'].values]).T ## ์ขŒํ‘œ๊ฐ’๋งŒ ์กด์žฌ, (N,2) array ์ƒ์„ฑ
 
# 2. BallTree ์ดˆ๊ธฐํ™” (์œ ํด๋ฆฌ๋””์•ˆ ๊ฑฐ๋ฆฌ, ๋ฏธํ„ฐ ๋‹จ์œ„)
tree = BallTree(coords, metrid = 'euclidean')
 
# 3. ํŠน์ • ๊ฑฐ๋ฆฌ ๋ฐ˜๊ฒฝ ์ด๋‚ด ์ธ๋ฑ์Šค ์ถ”์ถœ (์˜ˆ. 3000 ๋ฏธํ„ฐ)
neihbors_idx = tree.query_radius(coords, r = 3000) # ๊ฐ ๊ฒฉ์ž๋ณ„ ๊ฒฐ๊ณผ Index๋งŒ ๊ฐ€์ ธ์˜ค๊ธฐ
 
# 4. ์ถ”์ถœ ์˜ˆ์‹œ
# 0๋ฒˆ์งธ index ๊ฒฉ์ž ๊ธฐ์ค€ ๋ฐ˜๊ฒฝ 3000m ์ด๋‚ด์˜ ๊ฒฉ์ž๋“ค
gdf.iloc[neihbors_idx[0]] 

์ฐธ๊ณ ์‚ฌ์ดํŠธ