s16*_*210 5 numpy machine-learning nan python-3.x logistic-regression
编辑:我已经取得了重大进展.我目前的问题是在我上次编辑之后编写的,可以在没有上下文的情况下回答.
我目前在Coursera上关注Andrew Ng的机器学习课程,并尝试在今天实施逻辑回归.
符号:
X
是一个(m x n)
带有输入变量向量作为行的矩阵(m
训练n-1
变量样本,第一列的条目在任何地方都等于1表示一个常量).y
是预期输出样本的相应向量(m
条目向量等于0
或的列向量1
)theta
是模型系数的向量(带有n
条目的行向量)对于输入行向量x
,模型将预测sigmoid(x * theta.T)
正结果的概率.
这是我的Python3/numpy实现:
import numpy as np
def sigmoid(x):
return 1 / (1 + np.exp(-x))
vec_sigmoid = np.vectorize(sigmoid)
def logistic_cost(X, y, theta):
summands = np.multiply(y, np.log(vec_sigmoid(X*theta.T))) + np.multiply(1 - y, np.log(1 - vec_sigmoid(X*theta.T)))
return - np.sum(summands) / len(y)
def gradient_descent(X, y, learning_rate, num_iterations):
num_parameters = X.shape[1] # dim theta
theta = np.matrix([0.0 for i in range(num_parameters)]) # init theta
cost = [0.0 for i in range(num_iterations)]
for it in range(num_iterations):
error = np.repeat(vec_sigmoid(X * theta.T) - y, num_parameters, axis=1)
error_derivative = np.sum(np.multiply(error, X), axis=0)
theta = theta - (learning_rate / len(y)) * error_derivative
cost[it] = logistic_cost(X, y, theta)
return theta, cost
Run Code Online (Sandbox Code Playgroud)
这个实现似乎工作正常,但我在计算logistic-cost时遇到了问题.在某些时候,梯度下降算法收敛到一个非常好的拟合,theta
并发生以下情况:
对于某些X_i
具有预期结果的输入行将1
X * theta.T
变为具有良好余量的正数(例如23.207
).这将导致sigmoid(X_i * theta)
成为究竟 1.0000
(这是因为失去了精准,我认为).这是一个很好的预测(因为预期结果等于1
),但这会打破后勤成本的计算,因为np.log(1 - vec_sigmoid(X*theta.T))
将评估为NaN
.这应该不是问题,因为该项乘以1 - y = 0
,但一旦出现值NaN
,整个计算就会被打破(0 * NaN = NaN
).
我应该如何在向量化实现中处理这个问题,因为np.multiply(1 - y, np.log(1 - vec_sigmoid(X*theta.T)))
在每一行X
(不仅仅是哪里y = 0
)计算?
输入示例:
X = np.matrix([[1. , 0. , 0. ],
[1. , 1. , 0. ],
[1. , 0. , 1. ],
[1. , 0.5, 0.3],
[1. , 1. , 0.2]])
y = np.matrix([[0],
[1],
[1],
[0],
[1]])
Run Code Online (Sandbox Code Playgroud)
然后theta, _ = gradient_descent(X, y, 10000, 10000)
(是的,在这种情况下,我们可以设置这么大的学习率)将设置theta
为:
theta = np.matrix([[-3000.04008972, 3499.97995514, 4099.98797308]])
Run Code Online (Sandbox Code Playgroud)
这将导致vec_sigmoid(X * theta.T)
真正好的预测:
np.matrix([[0.00000000e+00], # 0
[1.00000000e+00], # 1
[1.00000000e+00], # 1
[1.95334953e-09], # nearly zero
[1.00000000e+00]]) # 1
Run Code Online (Sandbox Code Playgroud)
但logistic_cost(X, y, theta)
评估为NaN
.
编辑:
我提出了以下解决方案.我刚刚用以下logistic_cost
函数替换了函数:
def new_logistic_cost(X, y, theta):
term1 = vec_sigmoid(X*theta.T)
term1[y == 0] = 1
term2 = 1 - vec_sigmoid(X*theta.T)
term2[y == 1] = 1
summands = np.multiply(y, np.log(term1)) + np.multiply(1 - y, np.log(term2))
return - np.sum(summands) / len(y)
Run Code Online (Sandbox Code Playgroud)
通过使用掩码,我只计算log(1)
结果将乘以零的位置.现在log(0)
只会发生在梯度下降的错误实现中.
开放式问题:如何使此解决方案更加干净?是否有可能以更清洁的方式实现类似的效果?
如果您不介意使用 SciPy,您可以 importexpit
和xlog1py
from scipy.special
:
from scipy.special import expit, xlog1py
Run Code Online (Sandbox Code Playgroud)
并替换表达式
np.multiply(1 - y, np.log(1 - vec_sigmoid(X*theta.T)))
Run Code Online (Sandbox Code Playgroud)
和
xlog1py(1 - y, -expit(X*theta.T))
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
424 次 |
最近记录: |