방법론11분 읽기
합성패널은 어떻게 만들어지는가
가상 시민 한 명의 22칸 기록을 펼치고, 4,433명이 어떤 유형으로 나뉘며, 네 개의 질문에 각자 어떻게 답하는지를 실제 산출값으로 따라간다.
목차
Reble.ai는 현실 세계를 반영하는 동적 사회 시뮬레이션 엔진이다. 그 엔진의 부품 중 가장 자주 오해받는 것이 합성패널이다. "가상의 사람을 만들어 여론을 예측한다"는 설명은 맞지만, 그 한 문장만으로는 무엇이 관측이고 무엇이 가정인지 알 수 없다.
지난 글이 시스템 전체를 위에서 내려다봤다면, 이 글은 한 명에서 출발해 위로 올라간다. 합성패널 한 명을 펼쳐 22칸을 전부 보이고, 그 한 명이 질문에 어떻게 답하는지를 실제 파라미터로 계산해 보인 다음, 4,433명이 어떻게 하나의 결과가 되는지까지 따라간다.
이 글이 답하는 질문은 하나다. 합성패널 한 명은 무엇으로 이루어져 있고, 무엇을 묻으면 어떻게 답하는가.
1. 합성패널 한 명은 22개의 칸이다
추상적인 설명 대신 실제 기록 한 장을 그대로 펼친다.
KR-V2-281687의 전체 기록. 실존 인물이 아니며, 인구분포를 보존하도록 생성된 가상 시민이다. 칸 밝기는 정보의 출처 등급을 뜻한다.이 사람은 대전 동구에 사는 64세 여성이다. 고졸, 서비스직, 소득 1분위, 기혼, 전남 출신. 이념은 진보, 지지정당은 더불어민주당, 정치관심도는 낮음, 투표의향은 있음.
중요한 것은 22칸이 같은 자격을 갖지 않는다는 점이다.
| 등급 | 칸 수 | 내용 | 성격 |
|---|---|---|---|
| A | 10 | 거주지·시군구·성별·연령·학력·직업·소득·혼인·출신지역 | 통계청 인구총조사에서 직접 관측 |
| B | 4 | 이념·지지정당·정치관심도·투표의향 | 조사 데이터를 학습한 모델이 예측 |
| C | 8 | panel_id·확률값 3개·권역·이념3·셀비중·가중치 | 파이프라인이 계산 |
B등급 옆에는 반드시 확률이 따라붙는다. 이 사람의 _지지정당_proba는 0.565다. "민주당 지지자"라고 단정한 것이 아니라 56.5%의 확신으로 그렇게 분류했다는 뜻이고, 시스템은 이 불확실성을 끝까지 들고 간다.
2. 4,433명은 어디서 왔고, 몇 종류인가
79만 4,000명의 합성인구를 만들고, 정치 성향을 예측해 붙이고, 최신 여론조사에 맞춰 재보정한 뒤, 지역·성별·연령을 대표하는 1만 249명을 뽑는다. 그중 지지정당이 더불어민주당인 사람이 정확히 4,433명이다.
그러면 이 4,433명은 몇 종류의 사람인가.
가장 큰 유형은 「인천·경기 · 40대 · 여성 · 진보」로 145명이고, 혼자뿐인 유형이 27개 있다. 여기에 학력·직업·소득·혼인까지 넣으면 유형은 3,249개가 되고 한 유형당 평균 1.36명이 된다. 즉 거칠게 보면 202종이고, 세밀하게 보면 사실상 전원이 다른 사람이다.
속성별로 값이 몇 가지인지도 그대로 세어진다 — 권역 8, 연령대 7, 성별 2, 이념 5단계(진보·중도진보·중도·중도보수·보수), 학력 10, 직업 7, 소득 5분위, 혼인 4, 출신지역 17.
3. 표본을 실제 선거인단으로 되돌린다
여기까지는 "민주당 지지층"의 표본이지 "권리당원"이 아니다. 둘의 구조는 반대 방향으로 어긋나 있다.
표본에서 서울·인천·경기는 52.4%인데 실제 권리당원 구조에서는 42.1%다. 반대로 광주·전라는 표본 17.0%인데 실제로는 33.0%다. 그래서 호남 합성패널 한 명의 무게를 평균 1.94배로 올리고 수도권은 낮춘다.
이 조정 뒤에는 합성패널 한 명이 더 이상 한 명이 아니다. 어떤 사람은 수백 명을 대표하고 어떤 사람은 그보다 적게 대표한다. 도표 1의 weight 칸(1.033)이 그 값이다.
4. 무엇을 묻고, 어떻게 답하는가
합성패널은 만들어 놓고 끝나는 명단이 아니다. 질문을 받고 답하는 응답자다. 현재 이 패널이 답하는 질문은 네 개다.
여기가 사람과 다른 지점이다. 실제 응답자는 "김민석"이라고 하나를 고르지만, 합성패널은 「김민석 30.3% · 정청래 27.6% · 송영길 13.0% · 유보 29.1%」처럼 확률벡터로 답한다. 한 명 안에 여러 가능성이 동시에 들어 있고, 시뮬레이션이 한 번 돌 때마다 그 확률에 따라 한 장을 뽑는다.
그리고 유형이 다르면 같은 질문에 답이 확연히 달라진다.
읽는 법은 이렇다.
- 광주·전라 × 진보 (793명) — 국정 평가는 80% 긍정, 정당 지지는 민주 70%, 차기 대선주자도 김민석 27%, 당대표도 김민석 30%. 네 질문이 한 방향으로 정렬돼 있다.
- 대구·경북 × 보수 (667명) — 국정 평가 68% 부정, 국민의힘 63%. 그런데 당대표 질문에서는 유보가 47%다. 민주당 경선에 관심이 없다는 사실이 "무응답"이 아니라 유보 확률 47%라는 숫자로 표현된다.
- 인천·경기 × 중도 (1,662명) — 국정 평가가 49% 대 45%로 팽팽하고, 차기 대선주자에서 유보가 22%로 1위다. 마음을 정하지 않은 상태 자체가 하나의 응답으로 기록된다.
당대표 시뮬레이션이 쓰는 것은 q004 하나다. 다만 그대로 쓰지 않는다. 실제 투표지에는 "유보" 칸이 없으므로, 유보 확률을 제거하고 나머지 후보에게 비례 배분해 투표지 위의 확률로 바꾼다. 이것이 지난 글에서 말한 후보 선택확률 b다.
5. "투표하러 나올 것인가"는 확률로 답한다
두 번째 핵심 질문은 선택이 아니라 참여다. 이 답은 공식 하나로 계산된다.
τ = 1 / (1 + e^−(α_권역 + γ · z_연령)) γ = 1.0
z_연령 = 18-29 −1.532 · 30대 −0.675 · 40대 +0.118
50대 +0.680 · 60대 +1.634 · 70+ −0.225
α_권역 = 충청 −0.6455 · 부울경 +0.1443 · 제주 −0.9156
인천 −0.0055 · 강원·대구·경북 +0.0328
z_연령은 연령대별 투표 의향의 상대 순서만 담는다. 60대가 가장 높고 18~29세가 가장 낮으며, 70세 이상은 오히려 −0.225로 내려간다 — 거동 문제로 실제 참여가 떨어지는 현상이 그대로 들어 있다. α_권역은 이미 개표가 끝난 다섯 권역의 실측 투표율에 정확히 맞도록 역산한 값이다(재현 오차 0.0000%p).
앞서 펼친 그 사람에게 이 공식을 적용하면 이렇게 된다.
| 합성패널 | α (권역) | z (연령) | 참여확률 τ |
|---|---|---|---|
| 대전 동구 · 여성 64세 | −0.6455 | +1.634 | 72.9% |
| 인천 · 남성 55세 | −0.0055 | +0.680 | 66.3% |
| 부산 서구 · 여성 29세 | +0.1443 | −1.532 | 20.0% |
부산의 29세는 권역 자체는 참여율이 높은 곳(α가 양수)인데도 연령이 크게 끌어내려 20%에 그친다. 반대로 대전의 64세는 권역이 불리한데도 연령이 밀어 올려 72.9%가 된다. 같은 나이라도 사는 곳이 다르면, 같은 곳이라도 나이가 다르면 답이 달라진다 — 그것이 이 곡선 하나에 담겨 있다.
아직 개표되지 않은 권역에는 α가 없다. 그런 곳은 값을 하나로 정하지 않고 투표율 자체를 매번 추첨한다.
6. 한 명의 확률이 결과가 되기까지
이제 재료가 모두 모였다. 합성패널 한 명이 가진 것은 세 가지다 — 참여확률 τ, 후보 선택확률 b, 대표 인원 w.
권역별 예측 구성은 이렇게 계산된다.
ŝ = Σ (w · τ · b) / Σ (w · τ)
└ 많이 대표하고, 투표하러 나올 사람의 선택이 더 크게 반영된다
여기서 끝이 아니다. 인구 구성만으로 설명되지 않는 지역 차이(δ)를 실측에서 뽑아 더하고, 당원 70%와 국민여론조사 30%를 합치고, 과반 미달이면 3위 표 이양을 적용한다. 그리고 이 전체를 1만 5,000번 반복한다. 매번 투표율·지역 격차·이양률·연령 시나리오를 새로 추첨하기 때문에 결과는 하나의 숫자가 아니라 분포로 나온다.
지난 채점 글에서 이 파이프라인이 실제 개표와 얼마나 맞았는지 기록했다 — 최종 득표율은 1.2%p 차이로 맞혔고, 호남 격차에서는 12.8%p 편차가 났다.
결론
합성패널의 정체는 세 문장으로 줄일 수 있다.
첫째, 한 명은 22칸짜리 기록이다. 그중 10칸은 통계청에서 관측한 사실이고, 4칸은 조사를 학습한 모델의 예측이며, 8칸은 계산값이다. 어느 칸이 어느 등급인지가 파일에 남아 있다.
둘째, 한 명은 확률로 답한다. "김민석을 찍는다"가 아니라 "김민석 30.3%, 정청래 27.6%, 유보 29.1%"로 답하고, 참여 여부도 72.9%처럼 확률이다. 단정하지 않는 것이 이 설계의 핵심이다.
셋째, 4,433명은 202개 유형으로 갈리고 세밀하게는 3,249개로 갈린다. 유형마다 네 질문에 다르게 답하고, 그 차이가 가중치를 타고 최종 결과의 차이를 만든다.
그리고 반드시 덧붙여야 할 한계가 있다. 합성패널은 실존 인물이 아니다. 개인정보를 모아 만든 명단이 아니라 분포를 보존하도록 생성된 통계적 시민이며, panel_id는 합성 식별자다. 또한 이 패널에는 "실제 권리당원인가"를 나타내는 칸이 없어 "민주당 지지층의 특성이 권리당원과 비슷하다"는 가정이 들어간다. 지난 채점에서 호남 편차가 크게 난 지점도 바로 여기와 맞닿아 있다.
패널이 실제로 어떻게 움직이는지는 민주당 당대표 시뮬레이션에서 직접 조작해 볼 수 있다. 조건을 바꾸면 이 글에서 본 확률들이 어떻게 재계산되는지 화면에서 보인다.
🧑 독자 질문 — 합성패널 한 명은 몇 명인가
이 블로그와 합성패널 시뮬레이션을 해보고 가장 많이 나오는 질문 하나를 그대로 옮긴다.
합성패널 한 명은 실제 사람 한 명인가, 아니면 여러 명을 대표하는가? 그러면 합성패널 20명은 실제 사람 20명에 해당하는가?
짧게 답하면 아니다. 셋으로 나눠서 설명한다.
첫째, 한 명은 한 명이 아니다. 4,433명의 합성패널이 152만 7,261명의 권리당원을 대표하므로, 산술적으로 한 명이 평균 344.5명을 대표한다. 도표 1에서 본 weight 칸이 바로 그 몫을 정하는 값이다.
둘째, 그 몫이 사람마다 다르다. 3장에서 표본과 실제 구조를 맞추는 재가중을 했기 때문에, 어디에 사는 합성패널이냐에 따라 짊어지는 인원이 달라진다.
| 권역 | 합성패널 | 1명이 대표하는 실제 인원 | 평균 대비 |
|---|---|---|---|
| 광주·전라 | 752명 | 약 670명 | 1.95배 |
| 대전·세종·충청 | 520명 | 약 314명 | 0.91배 |
| 제주 | 146명 | 약 303명 | 0.88배 |
| 서울·인천·경기 | 2,322명 | 약 277명 | 0.80배 |
| 부산·울산·경남 | 379명 | 약 262명 | 0.76배 |
| 강원·대구·경북 | 314명 | 약 229명 | 0.66배 |
그래서 질문하신 "20명"의 답은 어디의 20명이냐에 달려 있다. 호남 합성패널 20명은 실제 권리당원 약 1만 3,404명분이고, 수도권 합성패널 20명은 약 5,538명분이다. 같은 20명인데 2.42배 차이가 난다. 표본에는 수도권이 훨씬 많이 뽑혔지만 실제 권리당원은 호남에 더 많이 몰려 있기 때문이다.
셋째, 그리고 애초에 1:1로 대응하는 실제 사람이 없다. 도표 1의 KR-V2-281687에 해당하는 실존 인물은 존재하지 않는다. 이 사람은 "대전 동구의 64세 여성 아무개"를 복제한 것이 아니라, "대전 동구에 사는 64세·고졸·서비스직·1분위·기혼 여성이라는 조건의 사람들이 인구 안에 이만큼 있다"는 사실을 한 줄로 대표하는 통계 단위다. 대응 관계는 개인 대 개인이 아니라 분포 대 분포다.
여기에 한 가지가 더 붙는다. 합성패널 한 명은 한 표도 아니다. 4장에서 봤듯 이 사람은 "김민석 30.3% · 정청래 27.6% · 유보 29.1%"처럼 확률로 답하므로, 1만 5,000번의 시뮬레이션에서 어떤 회차에는 김민석을, 어떤 회차에는 정청래를 선택한다. 참여 여부조차 72.9% 확률이라 안 나오는 회차도 있다. 한 명이 대표하는 것은 사람 수만이 아니라 그 사람들이 가진 가능성의 폭이기도 하다.
정리하면 이렇다. 합성패널 한 명은 평균 344명분의 무게를 지고, 그 무게는 지역에 따라 229명에서 670명까지 달라지며, 특정 실존 인물과는 대응하지 않고, 매 시뮬레이션마다 다르게 답할 수 있는 확률 묶음이다.
자료 출처 — 패널 원본 panel10k.csv(1만 249명 22속성), 질문별 산출 panel_q001~q004.json(각 전국 topline·권역×이념 24세그먼트), 참여함수 파라미터 turnout_calib.json(γ·z_연령·α_권역), 재가중 로직 member_panel.py, 선택·집계 로직 dp_choice.py. 유형 수·속성 가짓수·권역 비중은 panel10k.csv를 직접 집계한 값이고, 참여확률 표는 위 공식에 실제 파라미터를 넣어 계산한 값이다. 권리당원 목표 구조는 지난 글과 동일한 당 공표 자료 기준.