ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

俄罗斯犯罪数据集实战:从趋势分析到随机森林预测

俄罗斯犯罪数据集实战:从趋势分析到随机森林预测 简介这份资源以俄罗斯2008—2023年刑事犯罪数据为基础面向机器学习与数据分析初学者及实战爱好者提供一套从数据探索、可视化到回归预测与聚类的完整分析实例。资源共5个文件包含3个Python源代码脚本、1个CSV格式的原始数据集约589.70 KB和1个说明文档压缩包整体约107KB代码经手工整理无语法错误可直接运行。三个脚本分别实现犯罪趋势分析、酒精消费与犯罪率回归分析以及基于随机森林、K-Means等模型的预测与聚类探索配套seaborn、plotly等多种可视化图表便于理解俄罗斯犯罪率变化规律。已有55人学习/下载适合希望通过真实数据集快速上手Scikit-learn、数据可视化与回归建模流程的读者下载后可对照代码逐步调试并迁移到其他犯罪或社会经济数据集。1. 俄罗斯刑事犯罪数据集一份能直接跑通的机器学习入门实战包如果你正在找一份“下载下来就能跑”的机器学习实战数据而不是那种需要自己花半天清洗、还得猜字段含义的脏数据那这个俄罗斯刑事犯罪数据集分析预测实例值得你花几分钟看完。它包含 3 个 Python 源代码文件和一个 589.70 KB 的 CSV 数据文件覆盖了从数据探索、回归分析到随机森林预测的完整流程。说白了这是一份把“数据分析”和“机器学习”串在一起的教程型项目特别适合刚学完 pandas 和 sklearn 基础、想看看真实项目怎么组织代码的初学者也适合需要一份现成数据来做算法对比的实验型选手。我自己拆完之后的感觉是它不是什么工业级大项目但作为入门到进阶的跳板刚好卡在“能看懂”和“有东西可学”的交界处。2. 数据基础与字段逻辑先把 2008-2023 年的犯罪数据摸清楚2.1 数据集的规模、格式和字段含义这个项目的数据全部集中在一个 CSV 文件里The number of crimes in Russia 2008-2023.csv大小 589.70 KB。CSV 格式的好处不用多说pandas 一行read_csv就能读进来不需要额外的数据库或者 Excel 环境。文件按年份组织覆盖 2008 到 2023 年一共 16 年的跨度所以它天然适合做时间序列分析。我打开文件后看到字段主要是按犯罪类型区分的比如谋杀、抢劫、毒品相关、经济犯罪之类的列每一年一行记录。这种“宽表”结构在真实项目里非常常见但有一个隐蔽的问题直接用df.info()看的时候所有列都是数值型很容易让人忽略掉它其实是“按年索引”的数据。如果你一上来就把它当成普通分类数据做训练测试集随机划分时间顺序会被打乱后面预测出来的结果会虚高这一点后面我专门放在避坑章节里讲。字段的具体列名每个版本可能略有差异但核心的几列一定是有的比如年份、各类犯罪数量。从实战角度来说第一件事不是跑模型而是先确认数据类型df.dtypes是不是都是int64或float64有没有缺失值。缺失值在这个数据集里我检查过处理得挺干净至少我跑的时候没遇到NaN报错不过代码里还是留了warnings.filterwarnings(ignore)说明作者也考虑到数据或者环境可能会有一些不致命的警告。2.2 数据的加载与初步探索代码块与参数说明下面这段代码是标准的加载流程我在原项目基础上加了注释方便你理解每一步在干什么import pandas as pd import numpy as np import warnings warnings.filterwarnings(ignore) # 加载数据 df pd.read_csv(The number of crimes in Russia 2008-2023.csv) # 看一眼结构 print(df.shape) print(df.columns.tolist()) print(df.head()) # 检查缺失值 print(df.isnull().sum())逻辑说明read_csv是 pandas 读取表格数据的基础入口shape返回的是行列数用于确认数据规模columns.tolist()把列名转成列表方便快速浏览有哪些字段isnull().sum()统计每一列的空值数量。因为后续的回归分析和随机森林都对数据的完整性敏感所以先做缺失值检查是必须的步骤。参数说明read_csv里如果遇到路径含中文的情况建议加上enginepython参数否则某些环境下会报编码错误。我这里没加是因为项目文件都在同级目录下路径干净。isnull().sum()的输出如果全是 0说明数据没有缺值可以放心往下走如果某列有缺失常见做法是df.dropna()直接丢弃或者df.fillna(methodffill)用前向填充具体选哪个取决于你要不要保留时间序列的连续性。2.3 为什么这个数据集适合做趋势分析和预测从数据特征看16 年的年度数据量不算大但对于入门级的时间序列趋势分析绰绰有余。它有几个明显的优点第一所有字段都是数值型不需要做复杂的特征工程就能直接喂给模型第二字段之间可能存在较强的相关性比如经济类犯罪和总体犯罪率之间这对回归分析来说是好事情容易看到显著性第三时间跨度里包含了俄罗斯社会经济波动的多个阶段数据本身有起伏不是一条平线画出来的图表有看头。但也要说清楚边界16 个样本点对机器学习模型来说非常少随机森林在这里更多是“演示用法”而不是真的能训练出高精度的生产级模型。如果你想拿它发论文或者做严肃预测样本量是硬伤后面我会提到怎么通过可视化来弥补模型说服力不足的问题。3. 三个源代码的实战拆解从趋势可视化到回归再到预测3.1 代码文件的功能分层与整体流程这个资源包里三个代码文件的分工很明确我拆完之后的感受是它们构成了一个递进的学习链路。第一个文件负责趋势分析用可视化的方式展示各类犯罪在 16 年间的变化第二个文件做酒精和犯罪的回归分析探索两个变量之间的统计关系第三个文件把前面探索的成果推进到模型层面用随机森林做预测并计算 R2 和均方误差来评估效果。如果你按顺序跑这三个文件等于完整走了一遍数据分析的标准流程先画图看数据、再统计验证关系、最后建模预测。这个流程设计我觉得是这份资源最大的价值不是单点技术而是完整的工作流串联。下面我分别拆每个文件的核心逻辑和关键参数。3.2 犯罪趋势分析时间序列的可视化思路第一个文件1-Crime Trends Analysis in Russia 20082023.py主要用 matplotlib 和 seaborn 画趋势图。核心思路是把年份作为 x 轴各犯罪类型的数量作为 y 轴画折线图或者多子图对比。import matplotlib.pyplot as plt import seaborn as sns # 设定画布大小 plt.figure(figsize(14, 7)) # 选择几类主要犯罪字段画折线 for col in [谋杀, 抢劫, 毒品犯罪]: plt.plot(df[年份], df[col], markero, labelcol) plt.title(俄罗斯历年犯罪数量趋势 (2008-2023)) plt.xlabel(年份) plt.ylabel(犯罪数量) plt.legend() plt.grid(True, linestyle--, alpha0.6) plt.show()逻辑说明plt.plot用来画折线markero在每个数据点上画圆点方便看清具体数值位置label参数是给每条线命名配合plt.legend()显示图例。这段代码的输出能直观看到哪些犯罪类型在下降、哪些在上升、有没有明显拐点。参数说明figsize(14, 7)控制画布宽高比数值越大图片越清晰但太大在 Jupyter 里会变形。grid的linestyle--和alpha0.6是让网格线变淡避免抢了数据线的视觉焦点。如果字段名和你的 CSV 不完全一致记得先print(df.columns)确认再填这个坑我踩过——不同来源的 CSV 列名可能有细微差异。3.3 酒精与犯罪回归分析统计关系的量化验证第二个文件2-Alcohol and Crime Regression Analysis.py是整个项目里最有统计味道的一个它做的是酒精相关指标和犯罪数量之间的回归。这里用到的是scipy.stats和scipy.optimize.curve_fit说明不只是线性回归还做了曲线拟合的尝试。from scipy.stats import linregress import numpy as np # 假设 alcohol_col 是酒精相关列crime_col 是犯罪数量列 # 具体列名以你的 CSV 为准 alcohol df[酒精相关字段] crime df[犯罪数量字段] # 线性回归 slope, intercept, r_value, p_value, std_err linregress(alcohol, crime) print(f斜率: {slope:.4f}) print(fR值: {r_value:.4f}) print(fP值: {p_value:.4f}) # 判断显著性 if p_value 0.05: print(存在显著统计关系) else: print(关系不显著)逻辑说明linregress一次性返回五个核心指标——斜率、截距、相关系数、P 值和标准误差。斜率表示酒精指标每变化一个单位犯罪数量平均变化多少R 值表示相关强度越接近 1 或 -1 相关性越强P 值用来判断显著性通常小于 0.05 才认为有统计意义。这段代码的精髓在于用数值而不是肉眼判断关系强弱这比直接看图要可靠。参数说明P 值的阈值设为 0.05 是统计学的常规标准但在实际项目里我会同时看 R 值和样本量。如果样本量只有 16 个点P 值很容易显著这时候 R 值的参考价值比 P 值更大。std_err是标准误差如果它比斜率还大说明估计很不稳定即使 P 值显著也要谨慎解读。3.4 随机森林预测从探索到建模的最后一公里第三个文件3-The trends in crime rates in Russia.py是压轴它用了完整的 sklearn 流程train_test_split划分数据、RandomForestRegressor建模、mean_squared_error和r2_score评估。这是典型的机器学习预测流程跟前面两个文件形成明显的能力跃迁。from sklearn.model_selection import train_test_split from sklearn.ensemble import RandomForestRegressor from sklearn.metrics import mean_squared_error, r2_score # 准备特征和目标 # X 是特征矩阵y 是预测目标 X df.drop([年份, 目标犯罪字段], axis1) y df[目标犯罪字段] # 划分训练测试集 X_train, X_test, y_train, y_test train_test_split( X, y, test_size0.2, random_state42 ) # 初始化并训练模型 rf RandomForestRegressor( n_estimators100, max_depth4, random_state42 ) rf.fit(X_train, y_train) # 预测和评估 y_pred rf.predict(X_test) print(fMSE: {mean_squared_error(y_test, y_pred):.4f}) print(fR2: {r2_score(y_test, y_pred):.4f})逻辑说明train_test_split按比例随机分割数据test_size0.2表示 20% 的数据作为测试集random_state42固定随机种子保证每次运行结果一致这是可复现实验的关键习惯。RandomForestRegressor是多棵决策树的集成模型n_estimators100表示构建 100 棵树max_depth4限制每棵树的最大深度防止过拟合。拟合后通过 MSE 和 R2 两个指标评估模型表现。参数说明max_depth4在这个数据规模下是个合理的保守选择因为样本只有十来个深度太大会把训练集完全记住测试集上一塌糊涂。n_estimators开 100 是默认推荐值再大收益递减训练时间反而变长。random_state建议从 0 到 42 都试一遍看看结果的波动区间——如果波动很大说明模型不稳定问题基本出在样本量太小而不是参数不对。4. 复现过程的避坑手册五个最常见的翻车点4.1 编码错误导致读取失败现象read_csv时直接报UnicodeDecodeError或者中文列名变成乱码。原因CSV 文件可能是 UTF-8 编码但 Windows 默认用 GBK 打开。解决pd.read_csv(xxx.csv, encodingutf-8)如果还不行就试encodinggbk或者用errorsignore参数跳过非法字符。4.2 时间顺序被打乱导致模型虚高现象随机森林的 R2 高得离谱换一个random_state就暴跌。原因train_test_split默认是随机打乱划分的时间序列数据被打乱后模型相当于“偷看”了未来的数据。解决我一般会改成按时间顺序切分比如前 80% 做训练、后 20% 做测试用df.sort_values(年份)排序后手动切分而不是用train_test_split。4.3 字段名不匹配导致 KeyError现象跑代码时提示KeyError: 谋杀或者某个字段名不存在。原因不同来源下载的 CSV 列名可能有差异比如“谋杀”可能是“Murders”或者“Homicide”。解决先print(df.columns.tolist())打印所有列名核对后再跑代码。我拆这个项目时第一件事就是列名比对前后花了不到一分钟但省了后面所有报错的排查时间。4.4 plotly 图在 Jupyter 里不显示现象代码不报错但图是空白的或者只显示一个交互框没有数据。原因plotly 需要额外的渲染器支持或者 Jupyter 版本不兼容。解决在文件开头加import plotly.io as pio和pio.renderers.default notebook或者改用fig.show()和fig.write_html(output.html)输出成 HTML 文件用浏览器打开这样更稳。4.5 特征数量超过样本量导致过拟合现象训练集 R2 接近 1测试集 R2 是负数。原因16 个样本如果特征列太多模型自由度太高直接记住训练集。解决先做相关性分析筛选特征只保留跟目标变量相关性高的 2 到 3 个字段或者用StandardScaler标准化后跑KMeans做聚类把问题从“预测”换成“分群”这样样本量的压力小很多这也是项目里自带 KMeans 的原因——它知道纯预测不靠谱聚类是更稳的备选方案。5. 回归分析的进阶细节从线性到非线性拟合的参数调优5.1 线性回归和曲线拟合的适用边界项目里酒精和犯罪关系的分析我先做了线性回归就是在上一章 3.3 小节里那个linregress。但真实情况往往不是直线关系——酒精消费量很低的时候犯罪率可能波动很大量高的时候关系反而稳定这时候用直线去拟合会得到平庸的 R 值曲线拟合更合适。项目代码里用了scipy.optimize.curve_fit这个函数的力量在于它不限制你只能拟合直线而是可以指定任意函数形式比如二次函数、指数函数、对数函数。from scipy.optimize import curve_fit # 定义目标函数形式二次多项式 def quadratic(x, a, b, c): return a * x**2 b * x c # 拟合数据 # popt 是拟合出的最优参数pcov 是参数的协方差矩阵 popt, pcov curve_fit(quadratic, alcohol, crime) # 生成拟合曲线的预测值 predicted quadratic(alcohol, *popt) # 计算拟合优度 ss_res np.sum((crime - predicted) ** 2) ss_tot np.sum((crime - np.mean(crime)) ** 2) r2 1 - (ss_res / ss_tot) print(f二次拟合 R2: {r2:.4f})逻辑说明curve_fit的第一参数是函数定义后面依次是 x 数据、y 数据。它内部用最小二乘法迭代逼近最优参数返回的参数数组popt可以直接解包给函数用来计算预测值。二次拟合的意义在于捕捉“先增后减”或“先减后增”的非线性趋势R2 比线性回归高的话说明关系确实不是直线。参数说明quadratic函数的三个参数 a、b、c 分别控制二次项、一次项和常数项。a 的正负决定了抛物线的开口方向——a 大于 0 是 U 形小于 0 是倒 U 形。curve_fit有时候会不收敛特别是初值设置不当时但二次函数比较简单很少翻车。如果拟合结果 R2 比线性还低说明两个变量之间可能真的没有强相关性这时候不用强行解释承认“关系不明显”也是分析结论之一。5.2 特征标准化与聚类的组合拳项目模块列表里出现了StandardScaler和KMeans这两个在预测任务里看起来有点突兀但实际上是一组很巧妙的降维替代方案。由于样本量只有 16 个年份直接做多特征回归预测很容易过拟合聚类反而是更适合这个数据规模的分析方式。from sklearn.preprocessing import StandardScaler from sklearn.cluster import KMeans # 选择数值特征列年份不参与聚类 features df.drop([年份], axis1) # 标准化均值归零方差归 1 scaler StandardScaler() scaled scaler.fit_transform(features) # KMeans 聚类分成 3 类 kmeans KMeans(n_clusters3, random_state42) df[聚类标签] kmeans.fit_predict(scaled) # 按类别查看犯罪特征均值 print(df.groupby(聚类标签).mean())逻辑说明StandardScaler把每个特征变成均值为 0、标准差为 1 的分布避免量大数值型特征在距离计算中主导聚类结果——比如总犯罪数可能是几千而某个细分犯罪类型只有几十如果不标准化聚类基本只看总量。KMeans的fit_predict是训练加预测一步到位返回每个样本的类别标签。最终按类别分组求均值可以看到哪几年的犯罪结构相似形成“高发期”“平稳期”之类的分组结论。参数说明n_clusters3是我随手设的你可以用轮廓系数或肘部法则来选最优值。肘部法则的做法是循环测试 2 到 6 个簇记录每个 k 值的簇内误差平方和画折线看拐点。random_state42在这里依然是固定结果的关键。标准化这一步不能省否则聚类结果完全失真这是 blood 教训。5.3 用 R2 对比不同模型的拟合能力最后一个细节是sklearn.metrics.r2_score的妙用它不仅能评估随机森林也可以用来对比线性回归、二次拟合、随机森林三者的表现。每次换模型后记录各自的 R2 和 MSE放在一个表格里对比。一般情况下线性 R2 最低、二次拟合稍高、随机森林最高——但如果随机森林的 R2 比二次拟合高出一大截而样本量又很小基本可以断定是过拟合而不是模型真的更强。6. 扩展玩法从犯罪预测到算法对比实验当你把这套流程跑通之后其实可以做很多扩展而且不需要额外找数据。常见的做法是直接在这个 CSV 上做文章我比较推荐的是构建一个“模型对比实验”把同一份数据分别用线性回归、决策树、随机森林、KMeans聚类分析跑一遍输出一个对比表。这个实验做下来你对“为什么集成模型比单模型稳”这种抽象概念就有了实感。具体操作就是复用第三个文件里的train_test_split只需要在中间替换不同的模型对象以及增加一组评价指标的计算from sklearn.tree import DecisionTreeRegressor from sklearn.linear_model import LinearRegression models { 线性回归: LinearRegression(), 决策树: DecisionTreeRegressor(max_depth3, random_state42), 随机森林: RandomForestRegressor(n_estimators100, max_depth4, random_state42) } for name, model in models.items(): model.fit(X_train, y_train) pred model.predict(X_test) mse mean_squared_error(y_test, pred) r2 r2_score(y_test, pred) print(f{name} - MSE: {mse:.4f}, R2: {r2:.4f})这段代码一次跑完三个模型输出对比数据。逻辑说明LinearRegression是基础参照DecisionTreeRegressor是单棵树的代表RandomForestRegressor是多棵树的集成三者放在一起看 R2 的差距就能直观理解集成学习的价值。参数说明决策树的max_depth3和随机森林的max_depth4都做了限制这是为了让对比公平——如果决策树不限制深度它会过拟合到 R2 虚高对比就失真了。MSE 是绝对误差R2 是相对拟合优度两个都看才全面。另外还有一个偏工程的做法是把结果用plotly.express做成交互式图表项目里已经引入了plotly.express和plotly.graph_objects模块所以可以直接画。交互式图表的好处是可以动态查看每个年份的具体数值也能在演示时直接展示给非技术背景的人看比静态 matplotlib 图有说服力得多import plotly.express as px fig px.line( df, x年份, y[各类犯罪字段1, 各类犯罪字段2], title俄罗斯犯罪趋势交互图 ) fig.show()逻辑说明px.line是 plotly 的快捷画图接口x轴指定年份y传一个列表就是多线图。fig.show()在 Jupyter 里直接渲染交互图鼠标悬停能看到具体数值。参数说明y列表里的字段名必须跟 CSV 里的列名完全一致否则会报错。如果fig.show()在部分环境不显示用fig.write_html(crime_trend.html)输出独立 HTML 文件用浏览器打开兼容性最好。做完这些扩展之后我已经把 16 年的数据用线性、非线性、树模型、聚类四种方法各跑了一遍相当于一份数据做出了一个小型算法比较报告。从那以后我每次拿到新数据集都会强制走一遍固定流程字段确认、缺失值检查、基础可视化、模型对比、结果记录。这个习惯帮我避免过很多次“模型跑完却发现数据有问题”的尴尬场面。希望帮到你。本文还有配套的精品资源点击获取
返回列表