从头开始创建ML模型时卡住了

时间:2020-06-23 16:41:21

标签: python machine-learning deep-learning

我有一个包含8个参数的各种人的CSV文件,以确定该人是否患有糖尿病。 您将从here

获取CSV文件

我正在制作一个模型,用于训练和预测一个人是否患有糖尿病,而无需使用Tensorlfow Scikitlearn等第三方应用程序。我正在从头开始制作它。

这是我的代码:

from numpy import genfromtxt
import numpy as np

my_data = genfromtxt('E:/diabaties.csv', delimiter=',')

X,Y = my_data[1: ,:-1], my_data[1: ,-1:] #striping data and output from my_data


def 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 = 0
W,b = optimizer(W, b, X, Y, 100, 0.05) 

正在生成的输出是: It is in this link please take a look.

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

3 个答案:

答案 0 :(得分:0)

问题在于权重和偏差的初始化。重要的是,不要至少将权重初始化为零,而要使用一些随机的小数来初始化权重。 A的值变为零,使您的成本函数变得不确定

更新:

尝试这样的事情:

from numpy import genfromtxt
import numpy as np

# my_data = genfromtxt('E:/diabaties.csv', delimiter=',')

# X,Y = my_data[1: ,:-1], my_data[1: ,-1:] #striping data and output from my_data
# Using random data
n_points = 100
n_neurons = 5
X = np.random.rand(n_points, n_neurons) # 5 dimensional data from uniform distribution [0, 1)
Y = np.random.randint(low=0, high=2, size=(n_points, 1)) # Binary labels

def 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.random.normal(loc=0, scale=0.01, size=(n_neurons, 1))  # Drawing random initialization from gaussian
b = 0
W,b = optimizer(W, b, X, Y, 100, 0.05) 

答案 1 :(得分:0)

这个简短的答案是您的学习率大约是此问题的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中第二个值的数量向量必须调整为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_means
X /= col_stds
W, b = optimizer(W, b, X, Y, 100, 1.0)

在这里,我们减去每个特征的平均值,然后将每个特征的值除以其标准偏差。有时,新手会因此而被抛弃-“您无法更改数据值,从而改变了问题”-但是,如果您意识到这只是另一种数学转换,例如乘以W,加b,唯一的问题是您必须确保对将来的任何数据都做同样的事情。就像W向量的值是模型的学习参数一样,col_meanscol_stds的值也是如此,因此您必须像保存{{1} }和W,如果您以后想对新数据执行此模型的推断,请使用它们。

这使我们可以使用1.0更大的学习评分器,因为现在所有功能的大小都大致相同。

现在,如果尝试尝试,您将获得以下输出:

b

这就是您想要的。您的成本函数在每一步下降,并且在100次迭代结束时,成本稳定在8个有效数字左右,因此降低成本可能不会做太多。

欢迎使用机器学习!

答案 2 :(得分:0)

您的NaN问题仅仅是由于np.log遇到零值。您总是想缩放X值。统计(均值,std)归一化将起作用,但我发现最小-最大缩放效果最佳。这是该代码:

def minmax_scaler(x):
    min = np.nanmin(x, axis=0)
    max = np.nanmax(x, axis=0)
    return (x-min)/(max-min) 

此外,您的神经网络只有一个神经元。当您调用np.dot(X, W)时,它们应该分别是形状(大小,特征)和(特征,神经元)的矩阵。因此,现在您的初始化代码如下:

X = minmax_scaler(X)
neurons = 10
learning_rate = 0.05
W = np.random.random((X.shape[1], neurons)) 
b = np.zeros((1, neurons)) # b width to match W 

我获得了不错的融合,而无需更改学习率。参见图表:

Cost value converges

这是一个很小的数据集,即使有10-20个神经元,也有过拟合的危险。通常,您将编写一个predict()方法和一个准确性检查,然后保留一些数据以测试过度拟合。

相关问题