电影票房影响因素有很多,如影片质量、宣传、档期、排片、同期竞争、口碑等。灰色模型(GM) 常常用于对小规模数据进行预测分析。本文试图使用 GM(1,1) 对战狼 2 票房进行预测。
GM(1,1)
灰色系统内的一部分信息是已知的,另一部分信息是未知的,系统内各因素间有不确定的关系。
灰色预测是对既含有已知信息又含有不确定信息的系统进行预则,就是对在一定范围内变化的、与时间有关的灰色过程进行预测。灰色预测通过鉴别系统因素之间发展趋势的相异程度,即进行关联分析,并对 原始数据进行生成处理来寻找系统变动的规律,生成有较强规律性的数据序列,然后建立相应的微分方程模型,从而预测事物未来发展趋势的状况。
『注』更多详细介绍可以参考我的另一篇博文基于灰色模型(GM(1,1))的船舶事故预测研究
非周末特征
初步观察历史数据可以发现,周末票房明显增长,这也是合理的,因此周末和非周末分开预测。基于7月27~8月4日除去周末的历史票房,
使用 GM(1,1) 对未来 5 天工作日(8.07-8.11)预测,预测结果为:
[ 26592.85722754 26863.52726345 27136.95225974 27413.16025724,27692.17958215]
周末特征
基于周票房末数据即7月29,7月30,8月5号使用GM(1,1)对周日(8 .06) 票房预测,预测结果为:29942.36973182 万。
因此未来 6 天以后总票房预测达到 429990 万元。
为社么可以相信预测结果
其实在真正预测之前需要对模型的精度和准确性做估计,以非周末特征做为例,为了验证模型的准确性,我们选择7月27~8月3日中的非周末数据对8月4号票房做预测,预测结果为,26308.26947235,实际结果为 26340.9 相对误差 0.1%,娱乐而已,足矣!
写在最后
影响电影的票房因素有很多,本文使用 GM(1,1)预测,模型对内部的复杂关系进行了关联,最终做出了预测。当然如果未来的影响因素发生巨变,比如电影排期突然下降、甚至停播,那么预测结果将会受到巨大影响,因此预测纯属娱乐,仅供参考,不准轻喷。
最后放一张我在战狼中的照片[左一],其实只有几秒的镜头,我和班长站在舰长前面保卫着舰长,当冷锋干儿子跑过来的时候我说:“站住”,仅此而已!
源码
预测源码
使用方式,新建文件 gm.py,将一下代码复制到 gm.py 中,在文件目录下执行
># python gm.py
即可看到输出结果
# -*- coding: utf-8 -*-
import numpy as np
import math
def predict_func(history_data, m):
n = len(history_data)
X0 = np.array(history_data)
#累加生成
history_data_agg = [sum(history_data[0:i+1]) for i in range(n)]
X1 = np.array(history_data_agg)
#计算数据矩阵B和数据向量Y
B = np.zeros([n-1,2])
Y = np.zeros([n-1,1])
for i in range(0,n-1):
B[i][0] = -0.5*(X1[i] + X1[i+1])
B[i][1] = 1
Y[i][0] = X0[i+1]
#计算GM(1,1)微分方程的参数a和u
#A = np.zeros([2,1])
A = np.linalg.inv(B.T.dot(B)).dot(B.T).dot(Y)
a = A[0][0]
u = A[1][0]
#建立灰色预测模型
XX0 = np.zeros(n)
XX0[0] = X0[0]
for i in range(1,n):
XX0[i] = (X0[0] - u/a)*(1-math.exp(a))*math.exp(-a*(i));
#模型精度的后验差检验
e = 0 #求残差平均值
for i in range(0,n):
e += (X0[i] - XX0[i])
e /= n
#求历史数据平均值
aver = 0;
for i in range(0,n):
aver += X0[i]
aver /= n
#求历史数据方差
s12 = 0;
for i in range(0,n):
s12 += (X0[i]-aver)**2;
s12 /= n
#求残差方差
s22 = 0;
for i in range(0,n):
s22 += ((X0[i] - XX0[i]) - e)**2;
s22 /= n
#求后验差比值
C = s22 / s12
#求小误差概率
cout = 0.0
for i in range(0,n):
if abs((X0[i] - XX0[i]) - e) < 0.6754*math.sqrt(s12):
cout = cout+1
else:
cout = cout
P = (cout / n)
sum_pre = 0
if (C < 0.35 and P > 0.95):
#预测精度为一级
f = np.zeros(m)
for i in range(0,m):
f[i] = (X0[0] - u/a)*(1-math.exp(a))*math.exp(-a*(i+n))
# print f # 预测接下来 m 天各天票房
return sum(history_data) + sum(f) # 预测总票房
else:
print('灰色预测法不适用')
# 工作日数据: 7月27~8月4日除去周末
history_work_data = [9831.6,21226.6,27224.7,29118.1,27736.3,22375.8,26340.9]
m1 = 5
## 周末
history_weekend_data = [30988.6,36457.4,33049.7] # 周末数据,7月29,7月30,8月5号
m2 = 1
forcast_box = predict_func(history_work_data, m1) + predict_func(history_weekend_data, m2)
print("The forcast total box office of Wolf Warriors II is %d million after %d days"%(forcast_box,m1+m2))
验证源码
新建 gm_validation.py 复制一下内容,保存,执行:
># python gm_validation.py
即可看到输出结果
# -*- coding: utf-8 -*-
import numpy as np
import math
history_data = [9831.6,21226.6,27224.7,29118.1,27736.3,22375.8] # 8月4号: 26340.9
n = len(history_data)
X0 = np.array(history_data)
#累加生成
history_data_agg = [sum(history_data[0:i+1]) for i in range(n)]
X1 = np.array(history_data_agg)
#计算数据矩阵B和数据向量Y
B = np.zeros([n-1,2])
Y = np.zeros([n-1,1])
for i in range(0,n-1):
B[i][0] = -0.5*(X1[i] + X1[i+1])
B[i][1] = 1
Y[i][0] = X0[i+1]
#计算GM(1,1)微分方程的参数a和u
#A = np.zeros([2,1])
A = np.linalg.inv(B.T.dot(B)).dot(B.T).dot(Y)
a = A[0][0]
u = A[1][0]
#建立灰色预测模型
XX0 = np.zeros(n)
XX0[0] = X0[0]
for i in range(1,n):
XX0[i] = (X0[0] - u/a)*(1-math.exp(a))*math.exp(-a*(i));
#模型精度的后验差检验
e = 0 #求残差平均值
for i in range(0,n):
e += (X0[i] - XX0[i])
e /= n
#求历史数据平均值
aver = 0;
for i in range(0,n):
aver += X0[i]
aver /= n
#求历史数据方差
s12 = 0;
for i in range(0,n):
s12 += (X0[i]-aver)**2;
s12 /= n
#求残差方差
s22 = 0;
for i in range(0,n):
s22 += ((X0[i] - XX0[i]) - e)**2;
s22 /= n
#求后验差比值
C = s22 / s12
#求小误差概率
cout = 0.0
for i in range(0,n):
if abs((X0[i] - XX0[i]) - e) < 0.6754*math.sqrt(s12):
cout = cout+1
else:
cout = cout
P = (cout / n)
sum_pre = 0
if (C < 0.35 and P > 0.95):
m = 1 # 预测8月3号,8月4号
#预测精度为一级
f = np.zeros(m)
for i in range(0,m):
f[i] = (X0[0] - u/a)*(1-math.exp(a))*math.exp(-a*(i+n))
print f # 预测接下来 m 天各天票房
else:
print('灰色预测法不适用')
刚学的 Python,希望您宽广的胸怀能包它的存在,如果您有建议或意见可以通过邮件 [email protected] 与我取得联系。
申明: 预测结果仅代表个人观点,历史数据来自百度糯米电影