종 분포의 커널 밀도 추정

Beginner

This tutorial is from open-source community. Access the source code

소개

이 실험은 해버사인 거리 측정 기반의 볼 트리 (Ball Tree) 를 사용하여 지리 공간 데이터에 대한 이웃 기반 쿼리 (특히 커널 밀도 추정) 의 예시를 보여줍니다. 즉, 위도/경도 좌표상의 점들 간의 거리를 계산합니다. 데이터셋은 Phillips 등 (2006) 에서 제공합니다. 이 예제는 basemap 라이브러리를 사용하여 남아메리카의 해안선과 국경선을 플롯합니다.

VM 팁

VM 시작이 완료되면 왼쪽 상단 모서리를 클릭하여 Notebook 탭으로 전환하여 연습을 위한 Jupyter Notebook에 접근할 수 있습니다.

때때로 Jupyter Notebook 이 완전히 로드되기까지 몇 초 정도 기다려야 할 수 있습니다. Jupyter Notebook 의 제한으로 인해 작업 검증은 자동화될 수 없습니다.

학습 중 문제가 발생하면 Labby 에 문의하십시오. 세션 후 피드백을 제공하면 문제를 신속하게 해결해 드리겠습니다.

필요한 라이브러리 가져오기

첫 번째 단계는 이 실험에 필요한 라이브러리를 가져오는 것입니다. 이 실험에서는 numpy, matplotlib, fetch_species_distributions, 그리고 KernelDensity 라이브러리를 사용할 것입니다.

import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import fetch_species_distributions
from sklearn.neighbors import KernelDensity

데이터 로드

다음 단계는 Phillips 등 (2006) 에서 제공한 데이터를 로드하는 것입니다. 이 데이터셋에는 커널 밀도 추정을 보여주기 위해 사용할 두 종의 종류가 포함되어 있습니다.

data = fetch_species_distributions()
species_names = ["Bradypus Variegatus", "Microryzomys Minutus"]

데이터 준비

이제 커널 밀도 추정을 위해 데이터를 준비할 것입니다. 데이터셋에서 위도와 경도 정보를 추출하고 라디안으로 변환할 것입니다.

Xtrain = np.vstack([data["train"]["dd lat"], data["train"]["dd long"]]).T
ytrain = np.array(
    [d.decode("ascii").startswith("micro") for d in data["train"]["species"]],
    dtype="int",
)
Xtrain *= np.pi / 180.0  ## 위도/경도를 라디안으로 변환

그리드 생성

이제 배치 객체로부터 지도 그리드를 생성할 것입니다. construct_grids 함수를 사용하여 이 작업을 수행할 것입니다.

def construct_grids(batch):
    """배치 객체로부터 지도 그리드를 생성합니다.

    매개변수
    ----------
    batch : 배치 객체
        :func:`fetch_species_distributions` 함수에서 반환된 객체

    반환값
    -------
    (xgrid, ygrid) : 1 차원 배열
        batch.coverages 의 값에 해당하는 그리드
    """
    ## 모서리 셀의 x,y 좌표
    xmin = batch.x_left_lower_corner + batch.grid_size
    xmax = xmin + (batch.Nx * batch.grid_size)
    ymin = batch.y_left_lower_corner + batch.grid_size
    ymax = ymin + (batch.Ny * batch.grid_size)

    ## 그리드 셀의 x 좌표
    xgrid = np.arange(xmin, xmax, batch.grid_size)
    ## 그리드 셀의 y 좌표
    ygrid = np.arange(ymin, ymax, batch.grid_size)

    return (xgrid, ygrid)

## 함수를 호출하고 결과를 xgrid 와 ygrid 에 저장
xgrid, ygrid = construct_grids(data)

데이터 그리드 준비

등고선 플롯을 위한 데이터 그리드를 설정할 것입니다. construct_grids 함수를 사용하여 이 작업을 수행할 것입니다.

X, Y = np.meshgrid(xgrid[::5], ygrid[::5][::-1])
land_reference = data.coverages[6][::5, ::5]
land_mask = (land_reference > -9999).ravel()

xy = np.vstack([Y.ravel(), X.ravel()]).T
xy = xy[land_mask]
xy *= np.pi / 180.0

남아메리카 지도 플롯

이제 각 종의 분포를 보여주는 남아메리카 지도를 플롯할 것입니다.

fig = plt.figure()
fig.subplots_adjust(left=0.05, right=0.95, wspace=0.05)

for i in range(2):
    plt.subplot(1, 2, i + 1)

    print(" - 구면 좌표계에서 KDE 계산")
    kde = KernelDensity(
        bandwidth=0.04, metric="haversine", kernel="gaussian", algorithm="ball_tree"
    )
    kde.fit(Xtrain[ytrain == i])

    Z = np.full(land_mask.shape[0], -9999, dtype="int")
    Z[land_mask] = np.exp(kde.score_samples(xy))
    Z = Z.reshape(X.shape)

    levels = np.linspace(0, Z.max(), 25)
    plt.contourf(X, Y, Z, levels=levels, cmap=plt.cm.Reds)

    if basemap:
        print(" - basemap 을 사용하여 해안선 플롯")
        m = Basemap(
            projection="cyl",
            llcrnrlat=Y.min(),
            urcrnrlat=Y.max(),
            llcrnrlon=X.min(),
            urcrnrlon=X.max(),
            resolution="c",
        )
        m.drawcoastlines()
        m.drawcountries()
    else:
        print(" - 커버리지에서 해안선 플롯")
        plt.contour(
            X, Y, land_reference, levels=[-9998], colors="k", linestyles="solid"
        )
        plt.xticks([])
        plt.yticks([])

    plt.title(species_names[i])

plt.show()

요약

이 실험에서 지리 공간 데이터에 대한 커널 밀도 추정을 수행하는 방법을 배웠습니다. Phillips 등 (2006) 의 데이터셋을 사용하여 이 기술을 보여주었습니다. 또한 basemap 라이브러리를 사용하여 각 종의 분포를 보여주는 남아메리카 지도를 그리는 방법도 배웠습니다.