首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何将这段代码推广到多变量方程?

如何将这段代码推广到多变量方程?
EN

Stack Overflow用户
提问于 2016-04-23 09:06:24
回答 1查看 70关注 0票数 3

我是个口齿不清的新手。我正在学习吴家富在Coursera的机器学习课程(第一周还在继续)。我想尝试用LISP做线性回归。我编写了单变量线性回归的代码。代码似乎很好用。我想把它推广到多变量线性函数。我想知道怎么开始这么做。我想以这样的方式结束:

代码语言:javascript
复制
(defun run-linear-regression alpha iterations training-set number-of-variables (...))

它会产生一个假设发生器函数,其中包含变量的输入数,这些假设的偏导数函数等等。

下面是我到目前为止掌握的代码。我不需要任何人为我编码这一点,但一些指导如何去做我想做的,将不胜感激。此外,任何关于如何改进代码(性能、风格等)的一般性评论也是值得欢迎的。

代码语言:javascript
复制
(defun make-hypothesis (theta1 theta2)
  (lambda (x) 
    (+ theta1 (* x theta2))))

(defun make-cost-function (hypothesis)
  (lambda (training-data)
    (let* ((x (car training-data)) (y (cadr training-data))
       (val (- (funcall hypothesis x) y)))
      (* val val))))

(defun make-J-1 (cost-function)
  (lambda (training-set) (float 
              (/ 
               (reduce #'+ (mapcar cost-function training-set)) 
               (* 2 (length training-set))))))


(defun make-J (theta1 theta2)
  (make-J-1 (make-cost-function (make-hypothesis theta1 theta2))))

(defun make-part-deriv-1 (hypothesis)
  (lambda (test-set)
    (let ((m (length test-set)))
      (float (/
          (reduce #'+ (mapcar (lambda(elem)(- (funcall hypothesis (car elem)) (cadr elem))) test-set))
          m)))))

(defun make-part-deriv-2 (hypothesis)
  (lambda (test-set)
    (let ((m (length test-set)))
      (float (/
          (reduce #'+ (mapcar (lambda(elem)(* (- (funcall hypothesis (car elem)) (cadr elem)) (funcall hypothesis (car elem)))) test-set))
          m)))))

(defun make-learn-fn (alpha theta1 theta2 make-part-deriv)
  (lambda (test-set) 
    (let* ((hypothesis (make-hypothesis theta1 theta2)) (pdv (funcall make-part-deriv hypothesis)))
      (* alpha (funcall pdv test-set)))))

(defun make-learners (alpha)
  (list 
   (lambda (theta1 theta2 test-set) (- theta1 (funcall (make-learn-fn alpha theta1 theta2 #'make-part-deriv-1) test-set)))
   (lambda (theta1 theta2 test-set) (- theta2 (funcall (make-learn-fn alpha theta1 theta2 #'make-part-deriv-2) test-set)))))

(defun run-linear-regression (alpha iterations training-set &optional (theta1 0) (theta2 0) (printer nil))
  (let ((t1 theta1) (t2 theta2))
    (dotimes (i iterations)
      (if (not (null printer))
      (funcall printer t1 t2))
      (let* ((funcs (make-learners alpha))
         (nt1 (funcall (car funcs) t1 t2 training-set))
         (nt2 (funcall (cadr funcs) t1 t2 training-set)))
    (setq t1 nt1)
    (setq t2 nt2)))
    (list t1 t2)))

最后,我会这样说:

代码语言:javascript
复制
(defvar *training-set* '((15 20) (700 6) (23 15) (19 19) (204 15) (60 150) (87 98) (17 35) (523 29)))
(run-linear-regression 0.0001 1000000 *training-set*)
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-04-24 12:27:26

我不熟悉这里的数学,但由于没有其他人写出更好的答案,这里有一些一般性的建议。

您应该更改RUN-LINEAR-REGRESSION以获取一个变量列表,以及一个学习函数列表。例如:

代码语言:javascript
复制
(defun run-linear-regression (iterations training-set
                              variables learners)
  (let ((vars variables))
    (dotimes (i iterations)
      (setf vars (mapcar (lambda (function)
                           (funcall function vars training-set))
                         learners)))
    vars))

这是以学习者为论据,而不是让他们在函数中。您的原始代码使学习者在一个循环中学习,这似乎没有必要,因为MAKE-LEARNERS只使用ALPHA作为参数,而且这种情况永远不会改变,因此产生的学习者将永远是相同的。

我们还需要更改MAKE-LEARNERS,以便lambda函数将接受一个变量列表:

代码语言:javascript
复制
(defun make-learners (alpha)
  (list (lambda (variables test-set)
          (destructuring-bind (theta1 theta2) variables
            (- theta1 (funcall (make-learn-fn alpha theta1 theta2
                                              #'make-part-deriv-1)
                               test-set))))
        (lambda (variables test-set)
          (destructuring-bind (theta1 theta2) variables
            (- theta2 (funcall (make-learn-fn alpha theta1 theta2
                                              #'make-part-deriv-2)
                               test-set))))))

这与您拥有的基本相同,但它使用DESTRUCTURING-BIND从列表VARIABLES中提取THETA1THETA2。现在,我们可以像这样调用RUN-LINEAR-REGRESSION

代码语言:javascript
复制
(run-linear-regression 1000000 *training-set* '(0 0) (make-learners 0.0001))
;=> (42.93504 2.5061023e-4)

要添加更多的变量,您需要编写一个合适的MAKE-LEARNERS版本。因为我不懂数学,所以我不能做一个例子。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/36808789

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档