从头构建机器学习模型时遇到问题

我有一个包含8个参数的CSV文件,用于判断一个人是否患有糖尿病。你可以从这里获取该CSV文件。

我正在构建一个模型,用于训练和预测一个人是否患有糖尿病,而不使用TensorFlow、Scikit-learn等第三方应用程序。我是从头开始构建的。

这是我的代码:

from numpy import genfromtxtimport numpy as npmy_data = genfromtxt('E:/diabaties.csv', delimiter=',')X,Y = my_data[1: ,:-1], my_data[1: ,-1:] #striping data and output from my_datadef sigmoid(x):    return (1/(1+np.exp(-x)))m = X.shape[0]def propagate(W, b, X, Y):    #forward propagation    A = sigmoid(np.dot(X, W) + b)    cost = (- 1 / m) * np.sum(Y * np.log(A) + (1 - Y) * (np.log(1 - A)))    print(cost)    #backward propagation    dw = (1 / m) * np.dot(X.T, (A - Y))    db = (1 / m) * np.sum(A - Y)    return(dw, db, cost)def optimizer(W,b,X,Y,number_of_iterration,learning_rate):    for i in range(number_of_iterration):        dw, db, cost = propagate(W,b,X,Y)        W = W - learning_rate*dw        b = b - learning_rate*db    return(W, b)W = np.zeros((X.shape[1],1))b = 0W,b = optimizer(W, b, X, Y, 100, 0.05) 

生成的输出是:请查看这个链接中的内容。

我尝试过-用随机数初始化W的值。花了很多时间调试,但找不到我做错的地方


回答:

简短的回答是,你的学习率对于这个问题来说大了大约500倍。想象一下,你试图将你的W向量引导到成本函数的峡谷中。在每一步,梯度告诉你下坡的方向,但你在这个方向上的步伐太大,以至于你跳过了峡谷,最终到了另一边。每次发生这种情况时,你的成本都会上升,因为你离峡谷越来越远,直到在2次迭代后,成本值激增。

如果你将行W,b = optimizer(W, b, X, Y, 100, 0.05)

替换为

W,b = optimizer(W, b, X, Y, 100, 0.0001)

它将会收敛,尽管速度仍然不理想。(顺便说一句,没有好的方法知道给定问题需要的学习率。你只能尝试越来越低的值,直到你的成本值不发散。)

更长的回答是,问题在于你的特征都在不同的尺度上。

col_means = X.mean(axis=0)col_stds = X.std(axis=0)print('column means: ', col_means)print('column stdevs: ', col_stds)

结果是

column means:  [  3.84505208 120.89453125  69.10546875  20.53645833  79.79947917  31.99257812   0.4718763   33.24088542]column stdevs:  [  3.36738361  31.95179591  19.34320163  15.94182863 115.16894926   7.87902573   0.33111282  11.75257265]

这意味着第二个特征的数值变化大约是倒数第二个特征的数值变化的100倍,这反过来意味着你W向量中第二个值的调节精度需要是倒数第二个值的约100倍。

在实践中处理这个问题有两种方法。首先,你可以使用更高级的优化器。除了基本的梯度下降,你可以使用带动量的梯度下降,但这将改变你所有的代码。第二种更简单的方法是只需缩放你的特征,使它们大致相同大小。

col_means = X.mean(axis=0)col_stds = X.std(axis=0)print('column means: ', col_means)print('column stdevs: ', col_stds)X -= col_meansX /= col_stdsW, b = optimizer(W, b, X, Y, 100, 1.0)

在这里,我们从每个特征中减去其平均值,并将每个特征的值除以其标准差。有时新手会被这个方法弄糊涂——“你不能改变数据值,这会改变问题”——但如果你意识到这只是另一种数学变换,就像乘以W、加上b、取sigmoid等一样,它是有意义的。唯一的注意事项是你必须确保对未来的数据做同样的事情。就像你的W向量的值是你的模型的学习参数一样,col_meanscol_stds的值也是如此,所以你必须像保存Wb一样保存它们,并在将来使用这个模型对新数据进行推断时使用它们。

这样我们就可以使用更大的学习率1.0,因为现在所有特征的大小都大致相同了。

现在如果你尝试,你将得到以下输出:

column means:  [  3.84505208 120.89453125  69.10546875  20.53645833  79.79947917  31.99257812   0.4718763   33.24088542]column stdevs:  [  3.36738361  31.95179591  19.34320163  15.94182863 115.16894926   7.87902573   0.33111282  11.75257265]0.69314718055994520.59029575890790320.54817843781587320.5254804089153315...0.47099313212955620.47099312631935950.470993121221762730.47099311674880060.470993112823447

这就是你想要的。你的成本函数在每一步都在下降,在100次迭代结束时,成本稳定到大约8个有效数字,所以进一步降低可能不会有太大作用。

欢迎进入机器学习的世界!

Related Posts

使用LSTM在Python中预测未来值

这段代码可以预测指定股票的当前日期之前的值,但不能预测…

如何在gensim的word2vec模型中查找双词组的相似性

我有一个word2vec模型,假设我使用的是googl…

dask_xgboost.predict 可以工作但无法显示 – 数据必须是一维的

我试图使用 XGBoost 创建模型。 看起来我成功地…

ML Tuning – Cross Validation in Spark

我在https://spark.apache.org/…

如何在React JS中使用fetch从REST API获取预测

我正在开发一个应用程序,其中Flask REST AP…

如何分析ML.NET中多类分类预测得分数组?

我在ML.NET中创建了一个多类分类项目。该项目可以对…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注