岭回归需要多少空间?

时间:2016-12-03 15:20:48

标签: haskell machine-learning linear-algebra hmatrix

在Haskell中,ridge regression可以表示为:

import Numeric.LinearAlgebra 

createReadout :: Matrix Double → Matrix Double → Matrix Double
createReadout a b = oA <\> oB
  where
   μ = 1e-4

   oA = (a <> (tr a)) + (μ * (ident $ rows a))
   oB = a <> (tr b)

但是,此操作非常耗费内存。这是一个简约的示例,在我的机器上需要超过2GB并且需要3分钟才能执行。

import Numeric.LinearAlgebra
import System.Random

createReadout :: Matrix Double -> Matrix Double -> Matrix Double
createReadout a b = oA <\> oB
  where
    mu = 1e-4
    oA = (a <> (tr a)) + (mu * (ident $ rows a))
    oB = a <> (tr b)

teacher :: [Int] -> Int -> Int -> Matrix Double
teacher labelsList cols' correctRow = fromBlocks $ f <$> labelsList
  where ones = konst 1.0 (1, cols')
        zeros = konst 0.0 (1, cols')
        rows' = length labelsList
        f i | i == correctRow = [ones]
            | otherwise = [zeros]

glue :: Element t => [Matrix t] -> Matrix t
glue xs = fromBlocks [xs]

main :: IO ()
main = do

  let n = 1500  -- <- The constant to be increased
      m = 10000
      cols' = 12

  g <- newStdGen

  -- Stub data
  let labels = take m . map (`mod` 10) . randoms $ g :: [Int]
      a = (n >< (cols' * m)) $ take (cols' * m * n) $ randoms g :: Matrix Double
      teachers = zipWith (teacher [0..9]) (repeat cols') labels
      b = glue teachers

  print $ maxElement $ createReadout a b
  return ()
  

$ cabal exec ghc - -O2 Test.hs

     

$ time ./Test
  ./Test 190.16s用户5.22s系统106%cpu 3:03.93总计

问题是增加常数 n ,至少增加到n = 4000,而RAM限制为5GB。矩阵求逆运算在理论上需要的最小空间是多少?如何在空间方面优化此操作?可以用更便宜的方法有效地替换岭回归吗?

2 个答案:

答案 0 :(得分:1)

简单高斯 - 乔丹消除只占用空间来存储输入和输出矩阵以及恒定的辅助空间。如果我正确阅读,您需要反转的矩阵oAn x n,这样就不会有问题。

存储输入矩阵a完全控制了你的内存使用量,输入矩阵n = 4000使用至少1500 * 120000 * 8 = 1.34 GB。 a[i]=Integer.parseInt(s[i]);为4000 * 120000 * 8 = 3.58 GB,超出您预算空间的一半。我不知道你正在使用什么矩阵库或它如何存储它的矩阵,但如果它们在Haskell堆上,那么GC效应可以很容易地在空间使用中考虑另一个因子2。

答案 1 :(得分:1)

嗯,你可以获得3 * m + nxn的空间,但是数字稳定性如何,我不确定。

基础是身份

inv( inv(Q) + A'*A)) = Q - Q*A'*R*A*Q
where R = inv( I + A*Q*A')

如果A是你的A矩阵和

Q = inv( mu*I*mu*I) = I/(mu*mu)

然后你的岭回归的解决方案是

inv( inv(Q) + A'*A)) * A'*b

更多代数展示

inv( inv(Q) + A'*A)) = (I - A'*inv( (mu2 + A*A'))*A)/mu2
where mu2 = mu*m

注意,由于A是n×m,A * A&#39;是n x n。

所以一种算法就是

计算C = A * A&#39; + mu2

做一个胆怯的C分解,即找到上三角形U,这样U&#39; * U = C

计算向量y = A&#39; * b

计算向量z = A * y

在z

中解决U&#39; * u = z for u

对于z

中的v求解U * v = z

计算w = A&#39; * z

计算x =(y - w)/ mu2。