目录
- 代码
- 采集数据
- 简要分析
- 结论
代码
1、matlab代码
我借鉴了BP神经网络的实现实例,这个例子数据全部都给好了
%% I.清空环境变量
clear all
clc%% II.训练集/测试集的产生
%1.导入数据
x = xlsread('人口.xlsx',1,'A2:A72')';
y2 = xlsread('人口.xlsx',1,'C2:C72');
y3 = xlsread('人口.xlsx',1,'D2:D72');
y4 = xlsread('人口.xlsx',1,'E2:E72');
y5 = xlsread('人口.xlsx',1,'F2:F72');
y6 = xlsread('人口.xlsx',1,'G2:G72');
y7 = xlsread('人口.xlsx',1,'H2:H72');
y8 = xlsread('人口.xlsx',1,'I2:I72');
y9 = xlsread('人口.xlsx',1,'J2:J72');
y=[y2 y3 y4 y5 y6 y7 y8 y9];%采用8个因素来衡量
y1 = xlsread('人口.xlsx',1,'B2:B72'); %输出的结果,人口数%%
%2.随机产生训练集和测试集
%预测2020的出生人口数目,此时要从第2行读取到第73行
% temp = randperm(size(y,1)-1);
% temp(72)=72;
% %训练集--62个样本,要有足够的代表性,训练模型才能好,这里我采用随机产生的方法
% P_train = y(temp(1:62),:)';%P代表输入,T代表输出
% T_train = y1(temp(1:62),:)';
% %测试集--10个样本
% Year=x(temp(63:end));
% P_test = y(temp(63:end),:)';
% T_test = y1(temp(63:end),:)';
% N = size(P_test,2);%10
%固定训练
% P_train = y(1:61,:)';
% T_train = y1(1:61,:)';
% Year=x(62:end);
% P_test = y(62:end,:)';
% T_test = y1(62:end,:)';
% N = size(P_test,2);
%随机数训练temp = randperm(size(y,1));P_train = y(temp(1:61),:)';T_train = y1(temp(1:61),:)';Year=x(temp(62:end));P_test = y(temp(62:end),:)';T_test = y1(temp(62:end),:)';N = size(P_test,2);
%% III.数据归一化
[p_train, ps_input] = mapminmax(P_train,0,1);
p_test = mapminmax('apply',P_test,ps_input);
[t_train, ps_output] = mapminmax(T_train,0,1);%% IV.BP(Back Propagation)神经网络建立、训练及仿真测试
%1.创建网络
net = newff(p_train,t_train,9);%信号前向传播,误差反向传播,连接权值和阈值随机生成的
%单隐含层神经元%%
%2.设置训练参数
net.trainParam.epochs = 1000;
net.trainParam.goal = 1e-3;%训练要求精度
net.trainParam.lr = 0.001; %学习速率%%
%3.训练网络
net = train(net,p_train,t_train);%%
%4.仿真测试
t_sim = sim(net,p_test);%%
%5.数据反归一化
T_sim = mapminmax('reverse',t_sim,ps_output);%% V.性能评价
%%
% 1.相对误差error
error = abs(T_sim - T_test)./T_test;%%
% 2.决定系数R^2
R2 = (N * sum(T_sim .* T_test) - sum(T_sim) * sum(T_test))^2 / ((N * sum((T_sim).^2) - (sum(T_sim))^2) * (N * sum((T_test).^2) - (sum(T_test))^2));
%%
% 3.结果对比
result = [T_test' T_sim' error'];%% VI.绘图
figure
plot(1:N,T_test,'b:*',1:N,T_sim,'r-o');%2020年的真实值是用matlab拟合函数工具箱的拟合值,2020年的预测值是神经网络模型训练的预测值
legend('真实值','预测值'); %右上角标注
xlabel('预测样本') %x轴坐标描述
ylabel('人数(万)') %y轴坐标描述
set(gca, 'XTickLabels', Year);
string = {'测试人口数量预测结果对比';['R^2=' num2str(R2)]};
title(string);
采集数据
2. 数据来源
C-J列我认为是影响人口每年出生率的因素
1949-2019的数据,是我花了一天从国家统计局、年鉴、查阅论文或者是推算得到的数据,我就不给了,收集数据是要下功夫的,比如一年国赛中的出租车问题就需要去爬取数据,可以考虑爬虫~
简要分析
3. 分析
这个例子里面,由于我建模时间比较匆忙,所以其中输入神经元的八个特征值,我理想化认为都直接影响中国的每年出生人口的量纲。正常来说,应该对这八个因素进行逻辑回归分析和显著性水平检验,筛选掉一些显著性水平不达标的因素/特征值(例如就业人口等)。可以用多种模型和指标来进行探究。例如说AIC、BIC指标,引入激励函数,损失函数等方法。总而言之,还是很有意思的。
首先对这70年的人口数据进行分析,结合历史背景,我们可以清晰地看到在5年-10年的小时间段内,影响人口的主要因素。例如:
1)建国初期,国内外环境相对稳定,中国迎来了第一波婴儿潮;
2)1959年,1960年,1961年我国遭受三年自然灾害,图表1中可以看到这三年出生人口骤减。1961年-1963年是中国建国后70年人口增幅最大的两年,中国迎来第二波婴儿潮。
3)然而在2000-2015年的十五年之间,中国每年出生人口比较平缓。直到2016年之后,人口开始呈现明显的下降趋势。
图表1.中国每年出生人口的折线图
通过中国国家统计局和快易理财网的数据,共收集到九组数据,分别是中国每年出生人口、总人口统计(万/人)、人均GPA(按照美元算)、性别比例(按照女生等于100人计算)、人口自然增长率、城镇人口和乡村人口(两者加起来等于100)、美元兑换人民币汇率、总就业人口(万/人)。数据的范围从1949年不间断统计直到2019年为止。
我采用了BP 神经网络模型来预测中国每年的出生人口数据,表格中(详见“人口.xlsx”)每一行,分别利用总人口、人均GPA、性别比例、自然增长率、城镇人口、乡村人口、美元兑换人民币汇率、就业人口共八列数据作为特征值,来影响中国每年出生人口的数量。
为获得2020年特征值中的拟合数据
首先对八个特征值近10年-20年的数据进行分析,得到两种拟合的方向:
1、初步分析呈线性的数据:
包括“人口”表中的总人口、人均GPA、性别比例、城镇人口、乡村人口共5列的数据。我通过灰色模型GM(1,1)来对这五项数据进行预测,目的是得到未知的2020年的5项人口特征值。图表在GM(1,1)模型求解中展示
通过以上的分析,可以得到近似地拟合得到2020年的总人口数为140908万人,人均GDP为11158美元,男女比例为104.58:100,城乡村人口比例为61.65:38.35。之所以采用近十年来预测,是因为近十年我国在科技、军事、文化等方面飞速发展,综合国力和文化软实力显著提升,采用近十年的数据能较好地反应出中国在这一段时间内数据的总体趋势。
图表2.GPA
2、初步分析呈非线性的数据:
通过观察自然增长率、美元兑换人民币汇率和中国就业人口数据,可以发现近10年-20年,这些数据都是上下波动的。为此,我利用matlab数据拟合的工具箱Curve Fitting进行的拟合。
图表3.自然增长率
以上图表我就不一一给出!!!
结论
4.得出结论
matalb代码段的第三部分,我分别采用两种方式训练模型:
-
第一种是固定训练样本,采用了1949年-2010年共61/62年的训练样本,然后训练得到的结果非常不理想。我这里的评价指标采用了决定系数R^2以及相对误差矩阵。
图表4.评价指标
图表5.R^2太小了- 第一种是随机产生训练样本,采用了1949年-2019年间共61/62年的训练样本,然后训练得到的结果非常理想。但我们必须注意,神经网络虽然看起来好用,但是容易产生过拟合现象,需要进一步分析。matlab的黑箱子也比较难解释,所以慎用!!!
图表6.2020年预测样本
- 第一种是随机产生训练样本,采用了1949年-2019年间共61/62年的训练样本,然后训练得到的结果非常理想。但我们必须注意,神经网络虽然看起来好用,但是容易产生过拟合现象,需要进一步分析。matlab的黑箱子也比较难解释,所以慎用!!!
-
当我们要预测2020年出生人口数据的时候,要加多2020年这一列,因为要输入八个特征值以及拟合预测结果:
导入数据的代码块全部要改为:
x = xlsread('人口.xlsx',1,'A2:A73')';
y2 = xlsread('人口.xlsx',1,'C2:C73');
y3 = xlsread('人口.xlsx',1,'D2:D73');
y4 = xlsread('人口.xlsx',1,'E2:E73');
y5 = xlsread('人口.xlsx',1,'F2:F73');
y6 = xlsread('人口.xlsx',1,'G2:G73');
y7 = xlsread('人口.xlsx',1,'H2:H73');
y8 = xlsread('人口.xlsx',1,'I2:I73');
y9 = xlsread('人口.xlsx',1,'J2:J73');
y=[y2 y3 y4 y5 y6 y7 y8 y9];%采用8个因素来衡量
y1 = xlsread('人口.xlsx',1,'B2:B73'); %输出的结果,人口数
由于写的比较快,不足之处希望可以指正,希望大家国赛、美赛取得好成绩,考研保研出国都能一切顺利!
—————————————————————————————更新—————————————————————————————
之前有朋友在评论或者私信我说如何预测2060年或者2070年的数据,我在这里做一下解释。
在文章中我们要预测2020年的出生人口数据,首先我们要假定1950-2019年收集的数据是真实的,事实上也是我们从网站上爬取或者从文献中找到的数据,八九不离十。我们将这69年的数据喂入网络,用matlab的黑盒训练后,这个bp神经网络就有了一定的能力。这是什么能力呢?就是你输入一行八个特征值(上文中有提到,这也是我们定义的网络的输入神经元个数),网络就能给你输出一个数,这个数就是bp网络预测的出生人口数。
有不少人在看到这篇博文有点疑惑,我要预测2050年的数据,是不是要将1950年到2049年的数据都进行输入呢,也就是将 100 × 8 100\times8 100×8的矩阵输入到网络中,让网络学习。答案是否定的。这是为什么呢?因为你要获得2021-2049年的数据(现在是2021年底,今年的数据应该还没统计出来),只能通过拟合值来估计。就好像上文中我将每一列的数据通过matlab工具箱预测,得到2020的八个特征值输入数据(之前写这篇博文的时候是2020年,还没有2020年的数据),但这不一定准确,很有可能是fake的,存在比较大的出入。我用2000-2019预测2020的八个特征值都不一定准确了,更加何况预测今后30年的 30 × 8 30\times8 30×8的数据呢?那可能是灾难性的错误,如果将这些特征值输入网络,会导致网络的理解能力有很大偏差,甚至是不稳定。
但毫无疑问,你要让网络输出2050年的出生人口数,你得有2050年的八个特征值数据呀(人均GPA、性别比例等)。最简单的方法就是通过matlab工具箱预测,选择一个合适的拟合曲线去拟合数值。虽然这个数据不一定准确,但是我们的bp神经网络的理解能力是基本上准确的,因为输入的数据都是没有问题的。到这里,你应该明白了吧。最后一点我还想提一下,就是如果你要预测未来n年的数据,最好不要选择1978之前的年份数据输入网络中训练,因为在那一年的春天之后,我们的生活发生了很大的变化,陈旧的数据(生产力的差异太大)对预测未来还是有一定的影响。
——————————————————2022.6.13 更新——————————————————
本文的神经网络模型保存后,输入一行特征值就能预测任何一年的数据,而不需要一年年去测。