clojure - 与 Incanter 一起在 Clojure 中使用 BFGS 最小化算法进行 Logistic 回归

标签 clojure statistics machine-learning incanter logistic-regression

我正在尝试使用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 列矩阵转换为 nx1 行矩阵只会产生相同的错误和相反的错误。

:asize [1 2], :bsize [2 1]}

我在这里迷路了。

最佳答案

我不能对你的实现说任何话,但是incanter.optimize/minimize需要(至少)三个参数,而您只给它两个:

Arguments:
  f -- Objective function. Takes a collection of values and returns a scalar
       of the value of the function.
  start -- Collection of initial guesses for the minimum
  f-prime -- partial derivative of the objective function. Takes
             a collection of values and returns a collection of partial
             derivatives with respect to each variable. If this is not
             provided it will be estimated using gradient-fn.

不幸的是,我无法在这里直接告诉您要提供什么(对于f-prime?),但也许其他人可以。顺便说一句,我认为 ArityException Wrong number of args (2) Passed to [...] 在这里实际上非常有帮助。

编辑:实际上,我认为上面的文档字符串不正确,因为源代码没有使用 gradient-fn 来估计 f-prime.也许,您可以使用 incter.optimize/gradient 来生成您自己的?

关于clojure - 与 Incanter 一起在 Clojure 中使用 BFGS 最小化算法进行 Logistic 回归,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19886419/

相关文章:

python - 如果两个特征与目标变量完全相关,决策树如何在它们之间选择作为要 split 的根节点?

swing - 图标消失在由 Leiningen 制作的 uberjar 中

emacs - 使用 emacs+swank+slime+clojure 的良好工作流程?

machine-learning - 欧氏距离

r - 在 R 中执行预测模型的时间

python - 来自带有scipy的偏态分布的随机变量

binding - Clojure:在 let 绑定(bind)中展开 var

clojure - 如何在 map 内创建 map ?

statistics - 根据第一原理从离散概率分布中采样

java - Java 中的组合函数