欢迎光临
我们一直在努力

用 AI 辅助分析历史经济周期:按朝代切片的数据科学实验

用 AI 辅助分析历史经济周期:按朝代切片的数据科学实验

一、个性化深度引言

经济学教材上写着“经济危机大约每 10 年一次”,但这基于 20 世纪的工业经济数据。有没有可能从更长的历史维度看经济周期?

我们做了一次实验:将中国从秦汉到明清 2000 多年的经济史数据整理成结构化数据,用统计和机器学习方法分析周期性规律。这不是一个严谨的经济学研究——历史数据的质量远不能和现代统计数据相比。但方法论上有趣的发现是:即使数据充满噪声,一些跨朝代的统计规律仍然浮现出来。见证奇迹的时刻在于:当把朝代更替作为断点做结构性变化检验时,数据自己讲述了比教科书更丰富的故事。

二、个性化原理剖析

历史经济周期分析框架

数据处理中的关键挑战

1. 数据稀疏性

古代经济数据的覆盖度极不均匀。宋以后有相对详细的粮价记录,之前的只能靠《史记》《汉书》中的碎片化信息。处理方法:对稀疏时期使用线性插值,但必须标注插值区间以降低对分析结果的影响权重。

2. 计量单位不一致

唐代用“石”,宋代用“斗”,明代用“两”(白银)。需要在统一单位之前追溯每个朝代的度量衡换算关系。

3. 记录偏差

史书记录偏向“大事件”——大丰收、大饥荒、大规模战争。日常年份的数据反而是缺失的。这种“极端值偏向”会影响均值和方差的估计。

分析方法的选择

频谱分析:将时间序列转换到频域,寻找周期性成分。傅里叶变换 + 小波变换可用于非平稳序列。

结构断点检验:检验时间序列在朝代更替时是否存在结构性变化。Chow Test 或 Bai-Perron 检验。

事件研究法:以重大事件(如变法、战争)为中心,观察前后 N 年的经济指标变化模式。

三、个性化代码实践

import numpy as np
import pandas as pd
from typing import List, Dict, Tuple, Optional
from dataclasses import dataclass
from scipy import signal, stats
from collections import defaultdict

@dataclass
class Dynasty:
"""朝代数据结构"""
name: str
start_year: int
end_year: int
capital: str
notes: str = ""

class HistoricalEconomicAnalyzer:
"""
历史经济周期分析器

重要说明:历史数据的准确性有限
本分析目的是方法探索,结论需谨慎解释
"""

# 设计原因:中国主要朝代时间线
# 数据来源:《中国大百科全书》历史卷
# 朝代起止年份在学界有不同观点,此处采用通用分类
DYNASTIES = [
Dynasty("秦", -221, -206, "咸阳"),
Dynasty("西汉", -206, 8, "长安"),
Dynasty("新", 9, 23, "长安"),
Dynasty("东汉", 25, 220, "洛阳"),
Dynasty("三国", 220, 280, "多都"),
Dynasty("西晋", 265, 316, "洛阳"),
Dynasty("东晋", 317, 420, "建康"),
Dynasty("南北朝", 420, 589, "多都"),
Dynasty("隋", 581, 618, "大兴"),
Dynasty("唐", 618, 907, "长安"),
Dynasty("五代十国", 907, 960, "多都"),
Dynasty("北宋", 960, 1127, "开封"),
Dynasty("南宋", 1127, 1279, "临安"),
Dynasty("元", 1271, 1368, "大都"),
Dynasty("明", 1368, 1644, "北京"),
Dynasty("清", 1644, 1911, "北京"),
]

def __init__(self):
self.data: pd.DataFrame = None
self.results: Dict = {}

def generate_synthetic_data(self) -> pd.DataFrame:
"""
生成模拟历史经济数据

设计原因:真实古代经济数据的获取极为困难
此处用模拟数据展示分析方法框架
"""
np.random.seed(42)

# 时间范围:公元前 200 年到公元 1911 年
years = np.arange(-200, 1912)
n = len(years)

# 基础趋势:长期增长 + 周期成分
trend = 0.00001 * years # 极其缓慢的增长

# 设计原因:40-60 年周期(Kondratiev 波浪的假设)
cycle_60 = 0.3 * np.sin(2 * np.pi * years / 60)
cycle_120 = 0.2 * np.sin(2 * np.pi * years / 120)

# 朝代效应:每个朝代的基线水平略有不同
dynasty_effect = np.zeros(n)
for dyn in self.DYNASTIES:
mask = (years >= dyn.start_year) & (years <= dyn.end_year)
if mask.any():
# 设计原因:每个朝代的经济基线不同
dynasty_effect[mask] = np.random.normal(0, 0.15)

# 随机波动
noise = np.random.normal(0, 0.2, n)

# 合成经济指标(如:人均粮食产量指数)
economic_index = trend + cycle_60 + cycle_120 + dynasty_effect + noise

# 添加一些重大事件的冲击
events = {
-200: -0.5, # 秦末战乱
8: -0.3, # 王莽代汉
184: -0.4, # 黄巾起义
755: -0.6, # 安史之乱
1127: -0.5, # 靖康之变
1644: -0.4, # 明末农民起义
}
for year, shock in events.items():
if year in years:
idx = list(years).index(year)
# 冲击影响持续 5 年
for j in range(5):
if idx + j < n:
economic_index[idx + j] += shock * (0.8 ** j)

df = pd.DataFrame({
"year": years,
"economic_index": economic_index,
})

# 添加朝代标签
df["dynasty"] = "未知"
for dyn in self.DYNASTIES:
mask = (df["year"] >= dyn.start_year) & (df["year"] <= dyn.end_year)
df.loc[mask, "dynasty"] = dyn.name

return df

def spectral_analysis(
self, df: pd.DataFrame, indicator: str = "economic_index"
) -> Dict:
"""
频谱分析:寻找周期成分

设计原因:傅里叶变换将时域信号转为频域
峰值频率对应周期成分
"""
values = df[indicator].dropna().values

# 去趋势(避免趋势信号干扰周期检测)
from scipy.signal import detrend
detrended = detrend(values)

# 傅里叶变换
fft = np.fft.fft(detrended)
freqs = np.fft.fftfreq(len(detrended))

# 只考虑正频率
pos_mask = freqs > 0
freqs_pos = freqs[pos_mask]
power = np.abs(fft[pos_mask]) ** 2

# 找到峰值
from scipy.signal import find_peaks
peaks, properties = find_peaks(
power,
height=np.percentile(power, 95), # 只取最高 5%
distance=5,
)

# 设计原因:频率 → 周期(年)
peak_periods = []
for peak_idx in peaks:
if freqs_pos[peak_idx] > 0:
period = 1 / freqs_pos[peak_idx]
if 10 <= period <= 300: # 只关注 10-300 年的周期
peak_periods.append({
"period_years": round(period, 1),
"frequency": freqs_pos[peak_idx],
"power": power[peak_idx],
})

return {
"peak_periods": sorted(
peak_periods, key=lambda x: x["power"], reverse=True
)[:5], # Top 5
"dominant_period": peak_periods[0]["period_years"] if peak_periods else None,
}

def structural_break_test(
self,
df: pd.DataFrame,
indicator: str = "economic_index",
) -> pd.DataFrame:
"""
结构性变化检验:朝代更替是否为断点

设计原因:如果朝代更替是统计意义上的断点
说明政权变化对经济有实质性影响
"""
values = df[indicator].values
years = df["year"].values
n = len(values)

break_results = []

# 对每个朝代边界做检验
for i, dyn in enumerate(self.DYNASTIES):
# 找到朝代开始年份在数据中的位置
start_idx = np.searchsorted(years, dyn.start_year)
end_idx = np.searchsorted(years, dyn.end_year)

# 设计原因:断点前后至少需要 30 个数据点
if start_idx < 30 or (n – start_idx) < 30:
continue

# 简单版本:比较朝代前后 30 年的均值差异
before = values[max(0, start_idx-30):start_idx]
after = values[start_idx:min(n, start_idx+30)]

if len(before) > 0 and len(after) > 0:
t_stat, p_value = stats.ttest_ind(before, after)

break_results.append({
"dynasty": dyn.name,
"start_year": dyn.start_year,
"mean_before": np.mean(before),
"mean_after": np.mean(after),
"t_statistic": t_stat,
"p_value": p_value,
"significant_0.05": p_value < 0.05,
})

return pd.DataFrame(break_results)

def event_study(
self,
df: pd.DataFrame,
events: Dict[int, str],
window: int = 10,
) -> pd.DataFrame:
"""
事件研究法

设计原因:观测重大事件前后经济指标的变化模式
典型应用:变法、战争、自然灾害的影响评估
"""
all_windows = []

for year, event_name in events.items():
year_idx = df.index[df["year"] == year]
if len(year_idx) == 0:
continue

idx = year_idx[0]
start = max(0, idx – window)
end = min(len(df), idx + window + 1)

event_data = df.iloc[start:end].copy()
event_data["relative_year"] = range(
-min(idx – start, window),
min(end – idx, window + 1),
)
event_data["event"] = event_name
all_windows.append(event_data)

if not all_windows:
return pd.DataFrame()

return pd.concat(all_windows, ignore_index=True)

def run_full_analysis(self) -> Dict:
"""运行完整分析"""
print("=" * 60)
print("历史经济周期分析报告")
print("警告:本分析基于模拟数据,结论不能作为历史研究依据")
print("=" * 60)

# 生成数据
df = self.generate_synthetic_data()

# 1. 频谱分析
print("\\n1. 频谱分析(周期检测):")
spectrum = self.spectral_analysis(df)
print(f" 主导周期:{spectrum['dominant_period']} 年")
for p in spectrum["peak_periods"][:3]:
print(f" – {p['period_years']} 年周期(能量: {p['power']:.2f})")

# 2. 结构性断点检验
print("\\n2. 结构性断点检验(朝代更替):")
breaks = self.structural_break_test(df)
significant = breaks[breaks["significant_0.05"]]
print(f" 显著断点:{len(significant)} / {len(breaks)} 个朝代边界")
for _, row in significant.iterrows():
print(f" – {row['dynasty']}: "
f"均值 {row['mean_before']:.3f} → {row['mean_after']:.3f}"
f" (p={row['p_value']:.4f})")

# 3. 事件研究
print("\\n3. 事件研究(重大事件前后 10 年):")
events = {
-200: "秦统一六国",
755: "安史之乱",
1644: "明清更替",
}
event_data = self.event_study(df, events, window=10)

for event_name in events.values():
e_data = event_data[event_data["event"] == event_name]
if e_data.empty:
continue
before = e_data[e_data["relative_year"] < 0]["economic_index"].mean()
after = e_data[e_data["relative_year"] > 0]["economic_index"].mean()
change_pct = (after – before) / max(abs(before), 1e-8) * 100
print(f" – {event_name}: "
f"事件前后变化 {change_pct:+.1f}%")

return {
"spectrum": spectrum,
"breaks": breaks,
"event_data": event_data,
}

# 运行分析
analyzer = HistoricalEconomicAnalyzer()
results = analyzer.run_full_analysis()

print(f"\\n方法论的局限性:")
print(" 1. 古代经济数据来源有限且存在记录偏差")
print(" 2. 插值填补的数据降低了统计检验效力")
print(" 3. 相关关系不等于因果关系")
print(" 4. 本分析为方法演示,真实研究需要与历史学家合作")

四、个性化边界权衡

分析方法发现潜力数据要求可靠性适用性
频谱分析 周期规律 长序列 200+ 中(受插值影响) 寻找周期
结构断点检验 朝代更替影响 断点前后 30+ 中(依赖断点定义) 政策/制度评估
事件研究法 事件冲击 事件前后 5-10 年 低(混杂因素多) 短期影响评估
面板数据分析 地区差异 多地数据 30+ 区域比较
机器学习预测 模式识别 大量标注 低(因果混淆) 辅助假设生成

关键权衡:

  • 数据的质 vs 量的利用:古代经济数据的精度远不如现代数据。需要极其审慎地解释分析结果——"统计显著"不等于"历史真实"。分析结论应该作为假设提出,而非事实陈述。
  • 相关性 vs 因果性:任何时间序列分析都面临"相关不等于因果"的挑战。事件研究法中发现的事件前后变化,可能只是长期趋势的延续。
  • 方法严谨 vs 结论务实:在数据质量有限的情况下,过度追求统计方法的复杂性可能产生伪精确性。优选简单、可解释的方法。
  • 五、总结

    用 AI 和数据科学方法分析历史经济周期,核心价值不在结论而在方法。频谱分析可检测时间序列中的周期成分(40-60 年周期的假设在此框架下可检验),结构断点检验可判断朝代更替是否构成统计意义上的经济断点,事件研究法可观测重大事件的短期冲击模式。数据层面的三大挑战是:稀疏性(需要插值但必须标注不确定性)、单位不一致(需要跨朝代度量衡换算)、记录偏差(史书记录偏好极端事件)。工程上,建议采用多方法交叉验证(不同方法得出相似结论时才认真对待),并与历史学专业知识结合(统计分析不应脱离历史脉络的定性理解)。最终,这类分析的价值是生成可检验的假设,而非得出确定性的历史结论。

    赞(0)
    未经允许不得转载:171主机测评 » 用 AI 辅助分析历史经济周期:按朝代切片的数据科学实验
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址