实施类似机器学习的优化器

时间:2019-05-16 10:56:41

标签: python machine-learning

我正在尝试预测互联网帖子的趋势。

发布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 stands for 'how many hours to predict'

然后优化参数以使其更好一点。

我认为我可以使用机器学习,尽管我没有可用的GPU(是的,我在集成显卡上运行,怪莫哈韦),所以我正在尝试这种方法。

所以问题归结为,如何优化这些参数(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 # What is this?

 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()

1 个答案:

答案 0 :(得分:4)

您不需要ML来这样做(我认为这里过分杀伤力)。 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_minuten_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])*s
X = 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))])]).T
y = score 

然后:

popt, pcov = curve_fit(func, X, y) 

(如果我了解您的问题...否则,我看不出问题出在哪里)

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 = 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))])]).T
y = [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]