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和xlog1pyfrom 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 次 |
| 最近记录: |