简介
最近每天在CSDN更新一篇博客,在创作中心里,有很多博客的相关数据:
我就想,要是我一直坚持下去每天一篇,啥时候访问量能到1000,10000?对于这种问题,使用机器学习多项式回归很方便,只说不做不是我的风格,正好暑期比较闲,来分析一波。
数据获取与处理
首先,当然是数据的获取和处理,CSDN非常贴心地提供了导出数据的功能,导出格式为CSV。如你所见,后面三项全是0(疯狂暗示),所以这次只研究时间和访问数的关系。
使用python CSV包将数据导入:
def read_csv(self, filename):
f = open(filename + '.csv', encoding="utf-8")
infos = list(csv.reader(f))
y = []
for info in infos[1:]:
y.append((int)(info[1]))
self.train_y = np.array(y)
self.train_x = np.array([i for i in range(1,len(y)+1)])
然后绘制一个散点图看看:
def draw(self):
plot1 = plt.plot(self.train_x, self.train_y, 's', label='input')
# plot2 = plt.plot(self.predict_x, self.p1(self.predict_x), 'r', label='polyfit')
plt.xlabel('x')
plt.ylabel('y')
plt.xticks(self.train_x)
plt.legend()
plt.title('scatter')
plt.show()
最开始时,我直接用这个数据进行多项式拟合,预测结果不理想,因为我当前数据量较少,数据规律性不明显,机器学习时受到极端数据影响较大,也容易过拟合,导致预测结果不准确,那么怎么处理呢?
既然每日访问量有这样的问题,那么就试试总阅读量。同时,我们将数据分为两个部分,train集和test集(最后五组数据):
def read_csv(self, filename):
f = open(filename + '.csv', encoding="utf-8")
infos = list(csv.reader(f))
train_y = []
test_y = []
self.data_len = len(infos)
self.predict_x = np.array([i for i in range(self.data_len)]).reshape([-1, 1])
for index, info in enumerate(infos[1:]):
if index == 0:
train_y.append(int(info[1]))
elif index < len(infos) - 6:
train_y.append(int(info[1]) + train_y[index - 1])
elif index == len(infos) - 6:
test_y.append(int(info[1]) + train_y[index - 1])
else:
test_y.append(int(info[1]) + test_y[index - len(train_y) - 1])
self.train_x = np.array([i for i in range(1, len(train_y) + 1)])
self.train_x = np.array(self.train_x).reshape([len(self.train_x), 1])
self.train_y = np.array(train_y)
self.test_x = np.array([i for i in range(len(train_y) + 1, len(train_y) + len(test_y) + 1)])
self.test_x = np.array(self.test_x).reshape([len(self.test_x), 1])
self.test_y = np.array(test_y)
self.test_y = self.test_y.reshape([len(self.test_y), 1])
可以看到,这个时候图像的特征就比较明显了。
获得预测模型
这里使用的是scikit-learn库的多项式回归:
# 模型拟合
def predict(self):
poly_reg = PolynomialFeatures(degree=self.degree)
X_ploy = poly_reg.fit_transform(self.train_x) # 将数据处理成多项式特征
self.model = linear_model.LinearRegression() # 使用线性回归模型
self.model.fit(X_ploy, self.train_y)
# print("predict result:", self.model.predict(poly_reg.fit_transform(self.test_x)))
self.predict_x = poly_reg.fit_transform(self.predict_x)
self.predict_y = self.model.predict(self.predict_x)
print("r-squared:",self.model.score(poly_reg.fit_transform(self.test_x), self.test_y))
degree分别选取2,3,4,6,使用测试集对模型效果判断,sklearn中的score函数计算的是的R2(蓝点为训练数据,橙线为预测结果,橙点为测试数据):
可以看到:
degree=3时,模型拟合效果最好,对后五组数据的预测最准确
degree=2时,模型欠拟合(underfitting)
degree=4,6 时,模型过拟合(overfitting),导致预测不准确
使用模型进行预测
既然我们得到了需要的模型,那么下一步就是使用这个模型来完成最开始的目标,预测。
def get_day(self,visits):
poly_reg = PolynomialFeatures(degree=self.degree)
i = 0
while(True):
if self.model.predict(poly_reg.fit_transform([[i]]))[0]>visits:
print("预计第 %d 天阅读量到达 %d"%(i,visits))
return
i+=1
首先,试试1000:
作为一个有梦想的人,1000肯定是不能满足的:
总结
- 这篇博客纯属一时兴起,其实博客的访问量受很多方面的影响,有主观的如更新频率,内容丰富度等,也有客观的因素。对于我这种每天更新一篇无聊的算法博客来说,模型效果还是不错的,hhh。
- 得益于python的众多机器学习库,机器学习还是比较简单,而且这还是最简单的线性拟合。数据获取与处理才是最关键的。
- 由于当前数据量较少,所以模型效果不算太好(比如300天1,000,000还是有点难的),当数据变多之后,应该会有改善。
- 想不出第四点了,就这样了。