我正在尝试预测一个网络帖子的趋势。
我可以获得帖子发布2分钟后的评论数和投票数(可以更改,但应该足够)。
目前我使用以下公式:
predicted_votes = (votes_per_minute + n_comments * 60 * h) * k
然后我通过实验找到k
。我获取帖子数据,等待一个小时,然后进行
k = (older_k + actual_votes/predicted_votes) / 2
如此反复。这种方法有一定效果。准确率较低(40 – 50%),但它让我对帖子的反应有了一个大致的了解。
我在想是否可以使用更复杂的方程,例如:
predicted_votes = ((votes_per_minute * x + n_comments * y) * 60 * hour) * k # Hour表示'预测多少小时'
然后优化参数以获得更好的近似值。
我认为可以使用机器学习,尽管我没有可用的GPU(没错,我使用的是集成显卡,怪Mojave吧),所以我尝试了这种方法。
所以问题归结为,我如何优化这些参数(k,x,y
)以获得更高的准确性?
编辑:
我尝试按照@Alexis的建议去做,现在我到了这一步:
import numpy as np import matplotlib.pyplot as plt from scipy.optimize import curve_fit initial_votes_list = [1.41, 0.9, 0.94, 0.47, 0] initial_comment_list = [0, 3, 0, 1, 64] def func(x, k, t, s): votes_per_minute = x[0] n_comments = x[1] return ((votes_per_minute * t + n_comments * s) * 60) * k xdata = [1.41,0] y = func(xdata, 2.5, 1.3, 0.5) np.random.seed(1729) ydata = y + 5 plt.plot(xdata, ydata, 'b-', label='data') popt, pcov = curve_fit(func, xdata, ydata) plt.plot(xdata, func(xdata, *popt), 'g--', label='fit: a=%5.3f, b=%5.3f, c=%5.3f' % tuple(popt)) plt.xlabel('Time') plt.ylabel('Score') plt.legend() plt.show()
我不确定如何输入我有的数据(votes_per_minute, n_comments),也不知道如何告诉算法y
轴实际上是时间。
编辑2:
尝试按照@Alexis的建议去做,但我不知道actual_score
该用什么,一个数字不行,一个列表也不行..另外,我想预测的是’得分’而不是评论数量。
import numpy as np import matplotlib.pyplot as plt from scipy.optimize import curve_fit initial_votes_list = [1.41, 0.9, 0.94, 0.47, 0] initial_comment_list = [0, 3, 0, 1, 64] final_score = [26,12,13,14,229] def func(x,k,t,s): return ((x[0]*k+x[1]*t)*60*x[2])*s X = [[a,b,c] for a,b,c in zip(initial_votes_list,initial_comment_list,[i for i in range(len(initial_votes_list))])] y = actual_votes # 这是什么? popt, pcov = curve_fit(func, X, y) plt.plot(xdata, func(xdata, *popt), 'g--', label='fit: a=%5.3f, b=%5.3f, c=%5.3f' % tuple(popt)) plt.xlabel('Time') plt.ylabel('Score') plt.legend() plt.show()
回答:
你不需要使用机器学习来做这件事(我认为这里用机器学习有点大材小用)。Scipy提供了一种简单易用的方法来拟合你观察到的曲线。
scipy.optimize.curve_fit允许你将一个未知参数的函数拟合到你的观察数据上。由于你已经知道函数的总体形式,优化超参数是一个众所周知的统计问题,因此scipy应该足够了。
我们可以用一个小例子来演示这一点:首先我们生成数据
>>> import numpy as np>>> import matplotlib.pyplot as plt>>> from scipy.optimize import curve_fit>>>>>> def func(x, a, b, c):... return a * np.exp(-b * x) + c
定义带有一些噪声的数据进行拟合:
>>> xdata = np.linspace(0, 4, 50)>>> y = func(xdata, 2.5, 1.3, 0.5)>>> np.random.seed(1729)>>> y_noise = 0.2 * np.random.normal(size=xdata.size)>>> ydata = y + y_noise>>> plt.plot(xdata, ydata, 'b-', label='data')
然后我们使用scipy来拟合数据到函数(ax+b=y):
popt, pcov = curve_fit(func, xdata, ydata)
你可以为此添加约束,但对于你的问题来说没有必要。顺便说一句,这个例子在链接末尾我提供的页面上。你需要知道的关于使用曲线拟合的所有信息都可以在那个页面上找到。
编辑
看起来你很难弄清楚如何使用这个。让我们慢慢来,逐步分析以确保我们每一步都正确:
- 你想预测评论数量,这是你的
y
。它是已知的,不是计算出来的 - 你有三个输入参数:
votes_per_minute
,n_comments
和小时h
- 最后但同样重要的是,你有一个函数的三个参数
(x,y,k)
所以X[i]
(一个样本)应该看起来像这样:[votes_per_minute,n_comments,h]
,用你的公式y = ((votes_per_minute * k + n_comments * t) * 60 * h) * s
,通过替换名称:
def func(x,k,t,s): return ((x[0]*k+x[1]*t)*60*x[2])*sX = np.array([[a,b,c] for a,b,c in zip(initial_votes_list,initial_comment_list,[i for i in range(len(initial_votes_list))])]).Ty = score
然后:
popt, pcov = curve_fit(func, X, y)
(如果我理解你的问题…如果不是,我不明白问题出在哪里)
import numpy as npimport matplotlib.pyplot as pltfrom scipy.optimize import curve_fitinitial_votes_list = [1.41, 0.9, 0.94, 0.47, 0]initial_comment_list = [0, 3, 0, 1, 64]final_score = [26,12,13,14,229]def func(x,k,t,s): return ((x[0]*k+x[1]*t)*60*x[2])*sX = np.array([[a,b,c] for a,b,c in zip(initial_votes_list,initial_comment_list,[i for i in range(len(initial_votes_list))])]).Ty = [0.12,0.20,0.5,0.9,1] popt, pcov = curve_fit(func, X, y)print(popt)>>>[-6.65969099e+00 -6.99241803e-02 -9.33412000e-04]