【发布时间】:2013-11-22 01:52:25
【问题描述】:
我正在尝试使用 Incanter data analysis 库在 Clojure 中实现一个简单的逻辑回归示例。我已经成功编写了 Sigmoid 和 Cost 函数,但是 Incanter 的 BFGS 最小化函数似乎给我带来了一些麻烦。
(ns ml-clj.logistic
(:require [incanter.core :refer :all]
[incanter.optimize :refer :all]))
(defn sigmoid
"compute the inverse logit function, large positive numbers should be
close to 1, large negative numbers near 0,
z can be a scalar, vector or matrix.
sanity check: (sigmoid 0) should always evaluate to 0.5"
[z]
(div 1 (plus 1 (exp (minus z)))))
(defn cost-func
"computes the cost function (J) that will be minimized
inputs:params theta X matrix and Y vector"
[X y]
(let
[m (nrow X)
init-vals (matrix (take (ncol X) (repeat 0)))
z (mmult X init-vals)
h (sigmoid z)
f-half (mult (matrix (map - y)) (log (sigmoid (mmult X init-vals))))
s-half (mult (minus 1 y) (log (minus 1 (sigmoid (mmult X init-vals)))))
sub-tmp (minus f-half s-half)
J (mmult (/ 1 m) (reduce + sub-tmp))]
J))
当我尝试 (minimize (cost-func X y) (matrix [0 0])) 给 minimize 一个函数并启动参数时,REPL 会引发错误。
ArityException Wrong number of args (2) passed to: optimize$minimize clojure.lang.AFn.throwArity (AFn.java:437)
我对最小化函数到底期望什么感到非常困惑。
作为参考,我用 python 重写了它,所有代码都按预期运行,使用相同的最小化算法。
import numpy as np
import scipy as sp
data = np.loadtxt('testSet.txt', delimiter='\t')
X = data[:,0:2]
y = data[:, 2]
def sigmoid(X):
return 1.0 / (1.0 + np.e**(-1.0 * X))
def compute_cost(theta, X, y):
m = y.shape[0]
h = sigmoid(X.dot(theta.T))
J = y.T.dot(np.log(h)) + (1.0 - y.T).dot(np.log(1.0 - h))
cost = (-1.0 / m) * J.sum()
return cost
def fit_logistic(X,y):
initial_thetas = np.zeros((len(X[0]), 1))
myargs = (X, y)
theta = sp.optimize.fmin_bfgs(compute_cost, x0=initial_thetas,
args=myargs)
return theta
输出
Current function value: 0.594902
Iterations: 6
Function evaluations: 36
Gradient evaluations: 9
array([ 0.08108673, -0.12334958])
我不明白为什么 Python 代码可以成功运行,但我的 Clojure 实现却失败了。有什么建议?
更新
重读minimize 的文档字符串我一直在尝试计算cost-func 的导数,这会引发一个新错误。
(def grad (gradient cost-func (matrix [0 0])))
(minimize cost-func (matrix [0 0]) (grad (matrix [0 0]) X))
ExceptionInfo throw+: {:exception "Matrices of different sizes cannot be differenced.", :asize [2 1], :bsize [1 2]} clatrix.core/- (core.clj:950)
使用trans 将 1xn col 矩阵转换为 nx1 行矩阵只会产生相同的错误和相反的错误。
:asize [1 2], :bsize [2 1]}
我在这里迷路了。
【问题讨论】:
-
1) 为什么是
(minimize (cost-func X y) (matrix [0 0]))?第一个参数应该是cost-func而不是(cost-func X y)。 2)您应该将f-prime作为第三个参数。 -
好的,但是我在哪里传递我的数据呢? python 等效项有一个
args参数供我传递我的训练数据。我在minimize的文档字符串中没有看到类似的内容。 -
你可以使用闭包
标签: clojure statistics machine-learning incanter logistic-regression