9장 USITC 국제무역 중력 모형 추정#
1. 중력 방정식 이론#
중력 모형(gravity model)은 두 나라 간의 무역 흐름을, 마치 물리학에서 두 물체가 서로 끌어당기는 것처럼, 국가의 경제 규모와 거리 등의 요인에 기반하여 설명하는 모델이다. 쉽게 말해, 경제 규모가 큰 국가는 더 많은 무역을 하게 되고, 거리가 가까울수록 무역 비용이 낮아져 무역이 활성화된다는 기본 원리에 착안한다. 또한, 각 국가의 무역 접근성이나 시장 구조 등 다양한 요인을 고려하여, 실제 무역량이 왜 그렇게 나타나는지를 보다 정밀하게 분석한다.
미국국제무역위원회(USITC)가 제공하는 GME 모듈은 일반선형모형(GLM: Generalized Linear Model) 프레임워크에서 포아송 준최대가능도(PPML: Poisson Pseudo Maximum Likelihood) 기법을 사용하여 다음과 같은 중력 방정식(structural gravity equation)을 추정한다.
\(X_{ij}\) : \(i\)국에서 \(j\)국으로의 수출액
\(Y_i\) : \(i\)국의 국내 생산량
\(E_j\) : \(j\)국의 총지출
\(Y\) : 전세계 생산량
\(t_{ij}\) : \(i\)국과 \(j\)국 간의 양자간 무역 비용
\(\sigma\) : 서로 다른 원산지의 상품간 대체탄력성
위 식에서 \(S_i\)와 \(P_j\)는 각각 수출국과 수입국 내에서의 다자간 저항(resistance)을 나타내는데, 이는 \(i\)국의 수출 시장 접근 용이성과 \(j\)국의 수입 시장 접근 용이성을 의미한다.
식 (1)을 PPML을 사용하여 데이터에 적용할 때, 다양한 고정효과(fixed effect)를 포함시킬 수 있다. 패널 데이터를 사용할 경우, 중력 방정식 추정식 형태는 다음과 같다.
\(\gamma_{it}\) : 수출국의 시간에 따라 변하지 않는 고정효과
\(\eta_{jt}\) : 수입국의 시간에 따라 변하지 않는 고정효과
\(\lambda_{ij}\) : 수출국-수입국 간 시간에 따라 변하지 않는 고정효과
\(Z_{ijt}\) : 관세 수준처럼 시간에 따라 변하는 양자간 무역 결정 요인들의 벡터
만약 횡단면(cross-section) 데이터만 사용할 경우, 중력 방정식 추정식의 형태는 다음과 같다.
\(\gamma_i\) : 수출국 고정효과
\(\eta_j\) : 수입국 고정효과
\(Z_{ij}\) : 거리 등 양자간 무역 결정 요인들의 벡터
PPML 추정 기법을 사용하는 이유는 무역 데이터의 특성과 문제점을 효과적으로 다루기 위해서다. 무역 데이터는 종종 일부 국가 쌍에서 무역액이 0인 경우가 많고, 관측값의 분산이 평균에 비례하지 않는 경우가 있다. 이러한 상황에서는 전통적인 선형 추정 방법이 부적합할 수 있다. PPML은 이러한 제로 무역값과 이분산성(heteroskedasticity) 문제를 자연스럽게 처리하면서, 데이터의 조건부 평균을 올바르게 규정하여 추정값의 일관성을 보장한다.
2. GME 패키지 소개 및 설치#
소개#
미국국제무역위원회(USITC)의 Gravity Modeling Environment(GME) 패키지는 중력 무역 분석에 사용하기 위해 Python으로 작성된 도구들의 모음이다. 중력 모형, GME 패키지, 다양한 데이터 등에 대한 자세한 정보를 원한다면, USITC gravity portal을 방문하면 된다.
현재 릴리스된 GME 패키지는 세 가지 주요 구성 요소로 이루어져 있다: EstimationData 객체, EstimationModel 객체, estimate() 함수 등이다.
EstimationData객체는 추정에 사용될 데이터와 데이터에 관한 정보, 그리고 데이터의 기술적 분석을 용이하게 하는 도구 집합을 포함한다.EstimationModel객체는 모형 추정을 위한 명세(specification)를 설정하고 최종 결과 및 진단 정보를 저장하는 데 사용된다.estimate()함수는EstimationModel설정에 따라 PPML 추정을 실행한다.
GME 패키지 설치#
GME 패키지는 pandas, statsmodels, patsy, scipy 패키지를 필요로 한다. 만약 시스템에 이들이 아직 설치되어 있지 않다면, GME를 설치할 때 자동으로 설치된다.
설치
아래와 같이 GME 패키지를 다운로드하여 설치한다.
# 처음 한 번만 설치하면 됨
# !pip install gme
3. 기본 예제#
STEP 1: 필요 패키지 불러들이기#
import gme as gme
import pandas as pd
STEP 2: 데이터 규정#
GME 패키지는 EstimationData라는 데이터 객체를 기반으로 구축된다. EstimationData는 pandas 데이터 프레임 형태로 저장된 데이터와 함께, 다음과 같은 정보 및 도구들을 포함한다.
데이터 이력(Log): 데이터를 읽어온 파일의 위치나 수정 내역 등, 데이터에 대한 기록.
메타데이터(Metadata): 수입국, 수출국, 연도 정보가 포함된 열의 이름 등, 매번 따로 제공할 필요 없이 포함되는 정보.
요약 통계 및 기타 기술적(descriptive) 정보 도구: 자주 사용되는 기술적 정보를 산출하는 여러 도구.
예제 데이터 불러들이기
여기에서는 예제 무역 데이터(example_trade_and_grav_data_small.csv)를 로드한다. 참고로 USITC가 제공하는 데이터세트 International Trade and Production Database for Estimation (ITPD-E)는 1986년부터 2019년까지 265개국의 국제 및 국내 무역 데이터를 포함하며, 농업, 광업, 에너지, 제조업, 서비스 분야의 170개 산업에 대한 데이터를 포함하는 방대한 데이터세트다.
sample_data = pd.read_csv(
'https://www.usitc.gov/data/gravity/example_trade_and_grav_data_small.csv')
sample_data
| importer | exporter | year | trade_value | agree_pta | common_language | contiguity | log_distance | |
|---|---|---|---|---|---|---|---|---|
| 0 | AUS | BRA | 1989 | 3.035469e+08 | 0.0 | 1.0 | 0.0 | 9.553332 |
| 1 | AUS | CAN | 1989 | 8.769946e+08 | 0.0 | 1.0 | 0.0 | 9.637676 |
| 2 | AUS | CHE | 1989 | 4.005245e+08 | 0.0 | 1.0 | 0.0 | 9.687557 |
| 3 | AUS | DEU | 1989 | 2.468977e+09 | 0.0 | 0.0 | 0.0 | 9.675007 |
| 4 | AUS | DNK | 1989 | 1.763072e+08 | 0.0 | 1.0 | 0.0 | 9.657311 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 98607 | VEN | TWN | 2015 | 0.000000e+00 | 0.0 | 0.0 | 0.0 | 9.684672 |
| 98608 | VEN | ZAF | 2015 | 0.000000e+00 | 0.0 | 0.0 | 0.0 | 9.303873 |
| 98609 | VEN | KEN | 2015 | 0.000000e+00 | 0.0 | 0.0 | 0.0 | 9.363437 |
| 98610 | VEN | KWT | 2015 | 0.000000e+00 | 0.0 | 0.0 | 0.0 | 9.381265 |
| 98611 | VEN | URY | 2015 | 0.000000e+00 | 1.0 | 1.0 | 0.0 | 8.521421 |
98612 rows × 8 columns
변수 설명
importer: 수입국 국가 코드exporter: 수출국 국가 코드year: 무역 흐름이 발생한 연도trade_value: 무역 가치(화폐 단위로 측정)agree_pta: 양국간 특혜무역협정(PTA: Preferential Trade Agreement) 더미 변수 (1: 체결, 0: 미체결)common_language: 양국 공통 언어 사용 여부 더미 변수 (1: 공통 언어 존재, 0: 없음)contiguity: 양국이 국경을 접하는지 여부 더미 변수 (1: 국경 공유, 0: 공유하지 않음)log_distance: 두 국가간 거리를 자연 로그로 변환한 값
데이터 규정
다음으로, 위에서 불러들인 “sample_data”를 사용하여 EstimationData 인스턴스를 생성시켜 gme_data라는 이름으로 지정한다. 이를 위해서는 아래 방식으로 수입국/수출국, 무역 흐름, 연도, sector(해당되는 경우)와 같은 특정 주요 열의 이름을 제공해야 한다.
print 명령어는 EstimationData에 포함된 기본 요약 통계를 출력한다.
gme_data = gme.EstimationData(data_frame = sample_data,
imp_var_name = 'importer',
exp_var_name = 'exporter',
trade_var_name = 'trade_value',
year_var_name = 'year')
print(gme_data)
number of countries: 62
number of exporters: 62
number of importers: 62
number of years: 27
number of sectors: not_applicable
dimensions: (98612, 8)
EstimationData의 인자(argument), 속성(attribute), 메서드, 사용예 등에 대해서는 https://www.usitc.gov/data/gravity/gme_docs/api_docs/EstimationData/ 참조.
STEP 3: 모형 규정#
EstimationData 객체를 만든 후에는 이를 기반으로 EstimationModel 객체를 생성해야 한다. 이를 위해서는 데이터 객체인 EstimationData와 함께 모형 명세(specification)를 제공해야 한다. 아래에서는 EstimationModel 인스턴스 생성에 필요한 인자를 제공하고 이를 gme_model이라는 이름으로 지정한다.
gme_model = gme.EstimationModel(estimation_data = gme_data,
lhs_var = 'trade_value',
rhs_var = ['log_distance','agree_pta','common_language','contiguity'],
fixed_effects = ['importer', 'exporter'],
keep_years = [2015])
EstimationModel의 인자(Argument), 속성(Attribute), 메서드, 사용예 등에 대해서는 https://www.usitc.gov/data/gravity/gme_docs/api_docs/EstimationModel/ 참조.
STEP 4: 모형 추정#
EstimationModel이 정의되면, estimate() 메서드를 적용하여 모형을 추정할 수 있다.(코드 실행 과정에서 실행 상태에 대한 몇 가지 정보가 나오게끔 돼있다.)
estimate()메서드에 대한 자세한 설명은 https://www.usitc.gov/data/gravity/gme_docs/api_docs/estimate_method/ 참조.
gme_model.estimate()
Estimation began at 11:00 AM on Dec 11, 2025
Omitted Regressors: ['importer_fe_ARG', 'importer_fe_AUT', 'importer_fe_BEL', 'importer_fe_CHN', 'importer_fe_COL', 'importer_fe_DZA', 'importer_fe_EGY', 'importer_fe_GHA', 'importer_fe_IDN', 'importer_fe_IRN', 'importer_fe_ISR', 'importer_fe_KEN', 'importer_fe_KOR', 'importer_fe_KWT', 'importer_fe_LBY', 'importer_fe_MAR', 'importer_fe_NGA', 'importer_fe_NLD', 'importer_fe_PAK', 'importer_fe_SAU', 'importer_fe_SGP', 'importer_fe_THA', 'importer_fe_TUN', 'importer_fe_TWN', 'importer_fe_URY', 'importer_fe_VEN', 'importer_fe_ZAF', 'exporter_fe_ZAF']
Estimation completed at 11:00 AM on Dec 11, 2025
{'all': <statsmodels.genmod.generalized_linear_model.GLMResultsWrapper at 0x1f761db6630>}
추정 결과 반환
결과는
format_regression_table함수를 사용하여 간단한 표로 반환시킬 수 있다.아래 표에서 볼 수 있듯이 2015년 횡단면 데이터로 중력 모형을 추정한 결과, 양국간 특혜무역협정(
agree_pta)은 교역량을 유의하게 증가시킨다.또한 국경을 접하는 나라(
contiguity) 간에 교역량이 증가하는 경향이 통계적으로 유의하다.그러나 공통 언어 사용(
common_language)이 교역에 미치는 영향은 통계적으로 유의하지 않은 것으로 나타났다.
gme_model.format_regression_table(format = "txt")
| Variable | all | |
|---|---|---|
| a_agree_pta | agree_pta | 0.338*** |
| a_agree_pta_se | (0.088) | |
| a_common_language | common_language | 0.063 |
| a_common_language_se | (0.071) | |
| a_contiguity | contiguity | 0.211** |
| ... | ... | ... |
| a_log_distance_se | (0.051) | |
| b_aic | AIC | 1806014725995.583 |
| b_bic | BIC | 1806014667986.695 |
| b_llf | Likelihood | -903007362899.792 |
| b_nobs | Obs. | 2040 |
200 rows × 2 columns
GME모듈의 결과 반환(Results Manipulation) 함수에는format_regression_table,combine_sector_results,load_estimation,save_estimation,SlimResults등이 있다.
4. 중력 모형 추정#
이 튜토리얼은 데이터를 불러오고, 일부 요약 통계를 구성하며, 모형을 추정하고, 여러 가능한 형식으로 결과를 출력하는 기본적인 중력 분석을 시연한다.
데이터 불러오기#
데이터는 앞 절에서 사용한 예제 무역 데이터(example_trade_and_grav_data_small.csv)를 다시 한 번 사용한다.
gme 패키지는 데이터를 저장하기 위해 gme.EstimationData 객체를 사용한다. EstimationData는 추정에 사용되는 데이터세트(pandas DataFrame)와 해당 데이터에 관한 추가 정보, 그리고 데이터를 요약/조작하는 데 사용할 수 있는 다양한 메서드를 포함한다. 본 튜토리얼에서는 이러한 기능 중 일부를 시연한다.
먼저, gme.EstimationData를 생성하는 것부터 시작한다. 이를 위해서는 원하는 데이터세트(pandas DataFrame)와 데이터를 설명하는 여러 “메타데이터”를 입력해야 한다.
import gme as gme
import pandas as pd
gravity_data = pd.read_csv(
'https://www.usitc.gov/data/gravity/example_trade_and_grav_data_small.csv')
gravity_data
| importer | exporter | year | trade_value | agree_pta | common_language | contiguity | log_distance | |
|---|---|---|---|---|---|---|---|---|
| 0 | AUS | BRA | 1989 | 3.035469e+08 | 0.0 | 1.0 | 0.0 | 9.553332 |
| 1 | AUS | CAN | 1989 | 8.769946e+08 | 0.0 | 1.0 | 0.0 | 9.637676 |
| 2 | AUS | CHE | 1989 | 4.005245e+08 | 0.0 | 1.0 | 0.0 | 9.687557 |
| 3 | AUS | DEU | 1989 | 2.468977e+09 | 0.0 | 0.0 | 0.0 | 9.675007 |
| 4 | AUS | DNK | 1989 | 1.763072e+08 | 0.0 | 1.0 | 0.0 | 9.657311 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 98607 | VEN | TWN | 2015 | 0.000000e+00 | 0.0 | 0.0 | 0.0 | 9.684672 |
| 98608 | VEN | ZAF | 2015 | 0.000000e+00 | 0.0 | 0.0 | 0.0 | 9.303873 |
| 98609 | VEN | KEN | 2015 | 0.000000e+00 | 0.0 | 0.0 | 0.0 | 9.363437 |
| 98610 | VEN | KWT | 2015 | 0.000000e+00 | 0.0 | 0.0 | 0.0 | 9.381265 |
| 98611 | VEN | URY | 2015 | 0.000000e+00 | 1.0 | 1.0 | 0.0 | 8.521421 |
98612 rows × 8 columns
EstimationData 인스턴스 생성
gme_data = gme.EstimationData(data_frame=gravity_data,
imp_var_name='importer',
exp_var_name='exporter',
trade_var_name='trade_value',
year_var_name='year',
notes='Downloaded from https://www.usitc.gov/data/gravity/example_trade_and_grav_data_small.csv')
EstimationData 객체의 인스턴스를 생성하기 위해서는 원하는 데이터세트 이름과 함께 위에서 보듯이 여러 종류의 설명 인자(argument)들을 제공해야 한다. 이러한 인자들(imp_var_name, exp_var_name, trade_var_name, year_var_name)은 제공된 데이터세트에서 중력 모형 추정에 포함될 정보(각각 수입국, 수출국, 무역액, 연도 변수 이름)를 지정한다. 마지막으로, EstimationData에는 선택적으로 사용자가 나중에 참조할 수 있도록 문자열 리스트를 저장시킬 수 있다. 위 예에서는, 데이터 출처를 담은 notes를 입력하였다.
EstimationData 다루기#
gme.EstimationData는 gme.EstimationModel과 소통할 수 있는 객체 클래스를 제공하는 것이 주업무지만, 그것 이외에도 데이터 요약 및 조작을 위한 다양한 도구들을 함께 제공한다. 예를 들어, 아래에서처럼 객체를 단순히 호출(또는 출력)하면 데이터의 범위에 대한 요약 정보가 반환된다.
gme_data
number of countries: 62
number of exporters: 62
number of importers: 62
number of years: 27
number of sectors: not_applicable
dimensions: (98612, 8)
# 데이터세트의 수입국 수 반환
gme_data.number_of_importers
62
# 열 이름 리스트 반환
print(gme_data.columns)
['importer', 'exporter', 'year', 'trade_value', 'agree_pta', 'common_language', 'contiguity', 'log_distance']
# 연도 리스트 반환
print(gme_data.year_list())
[1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015]
# 각 연도별로 데이터세트에 포함된 나라 리스트를 담은 딕셔너리 반환
country_list = gme_data.countries_each_year()
print(country_list[1989])
['ITA', 'KOR', 'IDN', 'BOL', 'CHL', 'EGY', 'PHL', 'COL', 'NZL', 'CHN', 'POL', 'KWT', 'CAN', 'ECU', 'KEN', 'FRA', 'PRY', 'DNK', 'IRL', 'AUT', 'SDN', 'AUS', 'LBY', 'USA', 'ESP', 'TUN', 'DEU', 'TUR', 'MEX', 'IRN', 'ARG', 'DZA', 'THA', 'URY', 'PAK', 'PER', 'HUN', 'BRA', 'SWE', 'GBR', 'ISR', 'ZAF', 'NGA', 'GHA', 'IND', 'MAR', 'CHE', 'JPN', 'NLD', 'MYS', 'NOR', 'PRT', 'FIN', 'VEN', 'HKG', 'SAU', 'GRC', 'SGP', 'ISL']
# pandas 데이터 프레임의 여러 기술적(descriptive) 메서드.
gme_data.dtypes()
importer object
exporter object
year int64
trade_value float64
agree_pta float64
common_language float64
contiguity float64
log_distance float64
dtype: object
# pandas 데이터 프레임의 여러 기술적(descriptive) 메서드.
gme_data.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 98612 entries, 0 to 98611
Data columns (total 8 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 importer 98612 non-null object
1 exporter 98612 non-null object
2 year 98612 non-null int64
3 trade_value 98612 non-null float64
4 agree_pta 97676 non-null float64
5 common_language 97676 non-null float64
6 contiguity 97676 non-null float64
7 log_distance 97676 non-null float64
dtypes: float64(5), int64(1), object(2)
memory usage: 6.0+ MB
# pandas 데이터 프레임의 여러 기술적(descriptive) 메서드.
gme_data.describe()
| year | trade_value | agree_pta | common_language | contiguity | log_distance | |
|---|---|---|---|---|---|---|
| count | 98612.000000 | 9.861200e+04 | 97676.000000 | 97676.000000 | 97676.000000 | 97676.000000 |
| mean | 2002.210441 | 1.856316e+09 | 0.381547 | 0.380646 | 0.034051 | 8.722631 |
| std | 7.713050 | 1.004735e+10 | 0.485769 | 0.485548 | 0.181362 | 0.818818 |
| min | 1989.000000 | 0.000000e+00 | 0.000000 | 0.000000 | 0.000000 | 5.061335 |
| 25% | 1996.000000 | 1.084703e+06 | 0.000000 | 0.000000 | 0.000000 | 8.222970 |
| 50% | 2002.000000 | 6.597395e+07 | 0.000000 | 0.000000 | 0.000000 | 9.012502 |
| 75% | 2009.000000 | 6.125036e+08 | 1.000000 | 1.000000 | 0.000000 | 9.303026 |
| max | 2015.000000 | 4.977686e+11 | 1.000000 | 1.000000 | 1.000000 | 9.890765 |
추가로, EstimationData 객체는 제공된 데이터 프레임과 함께 작업할 수 있는 모든 기능을 그대로 유지한다. DataFrame은 EstimationData의 속성을 참조하여 쉽게 접근할 수 있다.
# 'trade_values' 열 반환
gme_data.data_frame['trade_value']
0 3.035469e+08
1 8.769946e+08
2 4.005245e+08
3 2.468977e+09
4 1.763072e+08
...
98607 0.000000e+00
98608 0.000000e+00
98609 0.000000e+00
98610 0.000000e+00
98611 0.000000e+00
Name: trade_value, Length: 98612, dtype: float64
모형 생성 및 추정#
EstimationData가 한 번 생성되면, 해당 데이터를 사용하여 중력 모형을 추정하는 것은 간단하다. 추정을 위한 기본 단계는 (1) 모형 정의와 (2) 모형 추정의 두 가지다.
모형 정의는 EstimationModel이라는 또 다른 객체를 생성하는 것을 의미한다. EstimationData와 마찬가지로, EstimationModel은 모형 명세(specification)를 정하고 추정할 때 일반적으로 취해지는 단계를 표준화하고 단순화하도록 설계되었다. EstimationData는 각 연구에서 한 번 생성되는 객체인 반면, EstimationModel은 다양한 명세를 테스트하면서 여러 번 정의될 가능성이 높다.
EstimationData와 마찬가지로, EstimationModel도 본질적으로 특정 모형의 특성을 정의하는 추가 정보가 포함된 데이터세트에 불과하다. 아래 예제들은 여러 모형 명세를 예시적으로 보여준다.
# 'trade_value'가 'log_distance', 'agree_pta' 등 변수에 의존하는 간단한 경우.
model_baseline = gme.EstimationModel(estimation_data = gme_data,
lhs_var = 'trade_value',
rhs_var = ['log_distance',
'agree_pta',
'common_language',
'contiguity'])
# 수입국-연도 고정효과 및 수출국-연도 고정효과를 포함시키는 경우.
fixed_effects_model = gme.EstimationModel(estimation_data = gme_data,
lhs_var = 'trade_value',
rhs_var = ['log_distance',
'agree_pta',
'common_language',
'contiguity'],
fixed_effects=[['importer','year'],
['exporter','year']])
# 데이터의 하위 집합을 사용하는 경우. 미국('USA')은 제외되고, 2013년부터 2015년까지만 포함된다.
data_subset_model = gme.EstimationModel(estimation_data = gme_data,
lhs_var = 'trade_value',
rhs_var = ['log_distance',
'agree_pta',
'common_language',
'contiguity'],
drop_imp_exp=['USA'],
keep_years=[2015, 2014, 2013])
모형을 지정할 때, 포함할 수 있는 몇 가지 주요 속성 유형이 있다:
모형 변수: 포함할 변수들은 각각 좌변의 종속변수와 우변의 독립변수를 나타내는
lhs_vars와rhs_vars인자를 사용하여 지정한다.고정효과(Fixed Effects): 모형이 추정될 때,
fixed_effects에 의해 지정된 경우 고정효과가 구성된다. 이는 단일 변수(예:['importer'])일 수도 있고, 상호작용 변수(예:[['importer', 'year']])일 수도 있다. 예를 들어,['importer', ['exporter', 'year']]를 입력하면, 수입국 고정효과 집합과 수출국-연도 고정효과 집합이 생성된다.데이터 하위 집합(Data Subsets): 추정에 사용할 데이터의 하위 집합은 다양한 방식으로 지정할 수 있다.
keep_years와drop_years인자를 사용하여 포함할 연도의 하위 집합을 선택할 수 있다. 유사하게keep_imp,keep_exp,keep_imp_exp인자와 해당하는drop_...옵션을 사용하여 수입국 및/또는 수출국에 대해 같은 작업을 수행할 수 있다.
모형이 정의되면, 제공된 명세에 따라 PPML 추정을 실행하는 것은 매우 간단하다. EstimationModel의 단일 메서드인 .estimate()를 호출하기만 하면 되며, 추가 입력은 필요하지 않다.
# 계산 시간을 줄이기 위해 일부 연도만 사용하여 새로운 고정효과 모형 정의
fixed_effects_model_2 = gme.EstimationModel(estimation_data = gme_data,
lhs_var = 'trade_value',
rhs_var = ['log_distance',
'agree_pta',
'common_language',
'contiguity'],
fixed_effects=[['importer','year'],
['exporter','year']],
keep_years = [2013,2014,2015])
# 고정효과 모형에 대해 PPML 추정 실행
estimates = fixed_effects_model_2.estimate()
Estimation began at 11:00 AM on Dec 11, 2025
Omitted Regressors: ['importer_year_fe_ARG2015', 'importer_year_fe_AUT2015', 'importer_year_fe_BEL2015', 'importer_year_fe_CHN2015', 'importer_year_fe_COL2015', 'importer_year_fe_DZA2015', 'importer_year_fe_EGY2015', 'importer_year_fe_GHA2014', 'importer_year_fe_GHA2015', 'importer_year_fe_IDN2015', 'importer_year_fe_IRN2013', 'importer_year_fe_IRN2014', 'importer_year_fe_IRN2015', 'importer_year_fe_ISR2015', 'importer_year_fe_KEN2014', 'importer_year_fe_KEN2015', 'importer_year_fe_KOR2015', 'importer_year_fe_KWT2015', 'importer_year_fe_LBY2013', 'importer_year_fe_LBY2014', 'importer_year_fe_LBY2015', 'importer_year_fe_MAR2015', 'importer_year_fe_NGA2015', 'importer_year_fe_NLD2015', 'importer_year_fe_PAK2015', 'importer_year_fe_SAU2014', 'importer_year_fe_SAU2015', 'importer_year_fe_SGP2015', 'importer_year_fe_THA2015', 'importer_year_fe_TUN2014', 'importer_year_fe_TUN2015', 'importer_year_fe_TWN2013', 'importer_year_fe_TWN2014', 'importer_year_fe_TWN2015', 'importer_year_fe_URY2015', 'importer_year_fe_VEN2014', 'importer_year_fe_VEN2015', 'importer_year_fe_ZAF2015', 'exporter_year_fe_ZAF2013', 'exporter_year_fe_ZAF2014', 'exporter_year_fe_ZAF2015']
Estimation completed at 11:00 AM on Dec 11, 2025
결과(추정치)는 딕셔너리로 저장된다. 또한, 추정 결과는 추정 모형의 속성인 EstimationModel.results_dict에 저장되어, 이 방법으로도 불러올 수 있다. 이러한 방식으로 결과를 저장하는 주된 이유는, 각각의 제품/산업/부문에 대해 별도로 모형을 추정하고 각 부문에 대한 추정 결과 집합을 반환하는 sector_by_sector를 용이하게 하기 위함이다. 여기서 고려한 예제와 같이 다수의 부문을 고려하지 않는 경우, 결과 딕셔너리에는 'all'이라는 키로 하나의 항목만 포함된다.
결과 보기, 포맷팅 및 출력#
회귀 추정치를 보기 위한 첫 번째 단계는, 저장된 딕셔너리에서 이를 풀어내는 것이다. 딕셔너리는 각 항목이 키와 연관되어 저장된 객체다. 해당 키를 사용하여 연관된 항목을 반환할 수 있다. 위의 예에서, estimates는 각 항목이 결과 객체인 딕셔너리다. 본 예에서는 단 한 번의 회귀만 수행되었으므로 하나의 객체만 존재한다. 반면, 여러 부문에 대해 각각 별도의 회귀를 수행하는 경우, 딕셔너리에는 각 부문의 이름을 키로 하여 여러 결과가 포함되게 된다.
# 객체의 키 리스트 반환
estimates.keys()
dict_keys(['all'])
# 결과 객체를 반환하고 새 이름으로 저장
results = estimates['all']
추정은 statsmodels 패키지의 도구들을 사용하여 결과 객체가 statsmodels GLM 결과 객체의 모든 기능을 상속받도록 한다. 이는 객체가 계수 추정치, 표준오차, \(p\)-값, AIC/BIC 등과 같은 다양한 필드를 포함한다는 것을 의미한다. 마찬가지로, 요약 테이블을 생성하는 데 사용할 수 있는 유용한 메서드가 객체에 포함되어 있다.
# 결과 요약 출력(길이가 너무 길어서 출력 생략함)
# results.summary()
# 추정된 파라미터 값 추출 (Pandas.Series로 반환됨)
coefficients = results.params
coefficients
log_distance -0.739840
agree_pta 0.334219
common_language 0.128770
contiguity 0.255161
importer_year_fe_ARG2013 26.980367
...
exporter_year_fe_USA2014 2.810464
exporter_year_fe_USA2015 2.958791
exporter_year_fe_VEN2013 -0.442260
exporter_year_fe_VEN2014 -0.490659
exporter_year_fe_VEN2015 -0.958928
Length: 329, dtype: float64
# 표준오차 추출
results.bse
log_distance 0.023879
agree_pta 0.042720
common_language 0.039384
contiguity 0.047051
importer_year_fe_ARG2013 0.361229
...
exporter_year_fe_USA2014 0.176461
exporter_year_fe_USA2015 0.223684
exporter_year_fe_VEN2013 0.314061
exporter_year_fe_VEN2014 0.308622
exporter_year_fe_VEN2015 0.346733
Length: 329, dtype: float64
# p-값 추출
results.pvalues
log_distance 9.316538e-211
agree_pta 5.134251e-15
common_language 1.076923e-03
contiguity 5.857618e-08
importer_year_fe_ARG2013 0.000000e+00
...
exporter_year_fe_USA2014 4.130107e-57
exporter_year_fe_USA2015 6.083029e-40
exporter_year_fe_VEN2013 1.590727e-01
exporter_year_fe_VEN2014 1.118707e-01
exporter_year_fe_VEN2015 5.681643e-03
Length: 329, dtype: float64
# 적합값(fitted value) 반환
results.fittedvalues
0 1.610136e+09
1 3.044133e+08
2 5.799368e+08
3 4.231019e+08
4 8.027580e+09
...
9355 1.393251e+10
9356 6.259130e+08
9357 6.597207e+09
9358 1.627117e+09
9359 1.329831e+10
Length: 8700, dtype: float64
추정 메서드는 회귀의 품질을 평가하는 데 도움이 되는 몇 가지 진단 정보를 제공한다. 이 정보에는 다중공선성(collinearities)이나 무역 부재로 인해 제거된 열의 리스트와 과적합 여부를 나타내는 지표가 포함된다.
# 진단 정보 반환
fixed_effects_model_2.ppml_diagnostics
Overfit Warning No
Number of Regressors Dropped 41
Regressors with Zero Trade [importer_year_fe_ARG2015, importer_year_fe_AU...
Regressors from User []
Regressors Perfectly Collinear [exporter_year_fe_ZAF2013, exporter_year_fe_ZA...
Completion Time 0.11 minutes
dtype: object
# 다중공선성으로 인해 제거된 전체 열 리스트 가져오기
fixed_effects_model_2.ppml_diagnostics['Regressors Perfectly Collinear']
['exporter_year_fe_ZAF2013',
'exporter_year_fe_ZAF2014',
'exporter_year_fe_ZAF2015']
gme 패키지는 Python 내외부에서 사용하기 위해 결과를 집계하고 형식을 지정하는 데 도움이 되는 여러 도구들을 제공한다. 이러한 도구들에는 여러 부문에서 모든 계수, 표준오차, \(p\)-값을 단일 데이터 프레임으로 가져오는 combine_sector_results() 메서드와, 프레젠테이션용으로 형식화된 테이블을 생성하여 텍스트 파일, CSV 파일 또는 LaTeX 파일로 내보낼 수 있는 format_regression_tables 메서드가 있다.
LaTeX 사용자: format_regression_table 메서드는 원하는 LaTeX 구문을 포함한 CSV 파일 형식으로 테이블을 출력할 수 있다. 이는 format='.csv'와 latex_syntax=True를 지정하여 수행할 수 있다.
5. GME 패키지 추정 방법론#
PPML 방식#
포아송 준최대가능도(PPML) 방식의 특징은 다음과 같다.
제로 무역값 처리:
무역 데이터에서는 많은 국가 쌍에서 실제 무역이 이루어지지 않아 무역액이 0인 경우가 많다. 전통적인 로그 변환 기반의 OLS 추정 방식은 0값을 처리할 수 없기 때문에 데이터를 왜곡하거나 일부 관측치를 제외해야 하는 문제가 발생한다. PPML 방식은 원래의 단위(수치) 그대로 추정하기 때문에 제로 무역값을 포함하여 분석할 수 있다.이분산성 문제 극복:
무역 데이터는 평균과 분산이 일정한 비율로 유지되지 않는 이분산성(heteroskedasticity) 문제를 자주 보인다. 중력 모형에서 이분산 문제란, 모형의 오차항(잔차)의 분산이 모든 관측치에서 일정하지 않고 관측치에 따라 달라지는 현상을 말한다. 예를 들어, 무역량이 큰 국가 쌍에서는 오차의 분산이 더 클 수 있으며, 이는 추정 결과의 표준오차나 신뢰구간 계산에 부정적인 영향을 미칠 수 있다. PPML은 조건부 평균의 명세만 정확하면 일관된 추정치를 제공할 수 있기 때문에, 이러한 이분산 문제에 대해 보다 견고한 결과를 산출할 수 있다.GLM 프레임워크의 유연성:
PPML은 일반선형모형(GLM) 프레임워크의 특수한 경우로, 다양한 고정효과나 추가 변수들을 쉽게 포함할 수 있는 장점을 가진다. 예를 들어, 국가별 특성, 시간 변화 효과, 또는 기타 무역 결정 요인들을 모형에 손쉽게 반영할 수 있어 현실적인 무역 상황을 더 정밀하게 모형화할 수 있다.추정의 일관성:
PPML은 조건부 평균을 올바르게 규정할 경우, 데이터의 분포 형태나 이분산 문제에 크게 영향을 받지 않고 일관된 추정치를 제공한다. 이는 특히 무역 데이터처럼 다양한 분포 특성을 보이는 경우에 큰 장점으로 작용한다.수치적 안정성:
PPML 방식은 비선형 추정 방법으로, 많은 무역 데이터에서 나타나는 극단적 값이나 관측치의 편차에 대해 보다 안정적으로 추정할 수 있다. 이는 특히 데이터의 분산이 큰 경우에 추정 결과의 신뢰도를 높여준다.
이러한 이유들로 인해 중력 방정식 모형을 추정할 때 PPML 방식은 제로 무역값, 이분산성, 다양한 고정효과 포함 등 실제 무역 데이터의 복잡한 특성을 효과적으로 다룰 수 있다.
추정 절차#
estimate 메서드는 수렴 가능성을 높이기 위한 데이터 진단과 함께 포아송 분포를 기반으로 부문별 GLM 추정을 수행한다. 만약 sector_by_sector 옵션이 지정되면, 해당 루틴은 각 부문에 대해 개별적으로 반복 실행되어 매번 별도의 모형을 추정한다. estimate 루틴은 EstimationModel에 제공된 모든 명세를 상속받는다.
PPML 구현의 기술적 세부 사항#
이 장에서 소개하는 GME 패키지는 Santos Silva와 Tenreyro (2006)의 방법을 따라 PPML을 구현한다. PPML은 분산이 평균에 비례한다고 가정하므로, PPML이 일관되게 추정되기 위해서는 조건부 평균의 올바른 명세가 유일한 조건이다. 또한, PPML은 추정 시 각 관측치에 동일한 가중치를 부여하므로, 무역 데이터의 이분산성 특성에 대한 정보가 많지 않을 때 바람직하다. Santos Silva와 Tenreyro (2006)는 PPML이 다양한 상황에서 잘 작동하며, 종속변수의 특정 유형의 측정 오류도 처리할 수 있음을 시뮬레이션 증거로 제시한다. 또한, PPML은 비선형 추정기법이므로 추정 시 제로 무역 흐름도 처리할 수 있다.
PPML 추정에서 일반적인 문제로는 완벽한 다중공선성(perfect collinearity)으로 인한 추정 불가능성과 알고리즘 실행 시 발생하는 수치적 어려움이 있다.
추정값이 존재하지 않는 경우#
Santos Silva와 Tenreyro (2010)는 종속변수의 양(+)의 관측치 하위 표본에서 완벽한 다중공선성이 존재할 경우(특정 연도나 부문에서 일부 국가가 무역을 하지 않아 \(X_{ij} > 0\)인 경우에 흔함), PPML 추정값이 존재하지 않을 수 있음을 보여준다. 이 경우, 추정 알고리즘이 수렴하지 않거나, \(X_{ij} = 0\)인 관측치에 대해 “완벽한” 적합을 보이는 가짜 수렴(spurious convergence)이 발생할 수 있다. 존재하지 않음을 확인하기 위해 Santos Silva와 Tenreyro (2011)는 문제 있는 회귀변수를 식별하여 제거한 후 PPML을 추정하는 간단한 STATA 코드를 사용한다. 이 코드는 모형이 가짜 수렴으로 인해 과적합되고 있음을 경고한다. GME 패키지는 Python에서 동일한 절차(문제 변수 식별 및 제거, 완벽한 다중공선성 테스트, \(X_{ij}=0\)인 관측치가 추정 모형에 의해 완벽하게 예측되는지 확인)를 수행하기 위해 해당 STATA 코드를 구현하였다. 이러한 모든 진단 정보는 PPML 진단으로 저장되어 매 GME 추정 후 사용자에게 제공된다.
수렴하지 않는 경우#
Santos Silva와 Tenreyro (2011)는 수치적 문제에 대한 민감성으로 인해 추정 알고리즘이 최대값을 찾지 못해 PPML 추정값을 찾지 못할 수 있음을 발견하였다. 특히, 서로 다른 크기의 다중공선성 회귀변수나 극단적이지만 완벽하지는 않은 다중공선성 회귀변수가 존재할 때 이러한 수치적 문제가 발생한다. 이들은 이러한 수치적 문제를 해결하기 위해 반복 가중 최소제곱법(Iteratively Reweighted Least Squares, IRLS)을 최적화 알고리즘으로 사용할 것을 권장하는데, 이는 GME에서 사용하는 statsmodels 패키지의 GLM 추정의 기본 방법이기도 하다. 따라서 GME의 PPML 추정기법은 서로 다른 데이터 구성으로 인한 수치적 문제에 대해 견고하다.