Я пробовал прилагаемый код для linear regression with automatic differentiation. Указывает тип данных [Двойной] [2], выполненный из двух плавающих элементов, и объявляет его экземпляром Num, Fractional и Floating. Как и во всех задачах фитинга/регрессии, существует функция скалярной стоимости, параметризованная параметрами подгонки c и m, и оптимизатор, который улучшает оценку этих двух параметров с помощью градиентного спуска.«Нет экземпляра для ..», код Haskell'98 на GHC7.8.3
Вопрос Я использую GHC 7.8.3, и авторы явно указать, что это H98 код (я упомянул об этом в названии, потому что это единственное существенное различие, которое я могу думать между моей установкой и автором , однако plz правильно, если неправильно). Почему он задыхается в определении функции стоимости? Мое понимание: функции idD и constD map Floats to Duals, g является полиморфным (он может выполнять алгебраические операции с двумя входами, потому что Dual наследуется от Num, Fractional и Floating) и производные карты Duals to Doubles. Подразумевается сигнатура типа для g (функция сокращения стоимости по этане по данным). Я попытался опустить его и сделать его более общим, заменив ограничение Floating на Fractional. Кроме того, я попытался преобразовать числовые типы c и m inline с (fromIntegral c :: Double), но безрезультатно.
Конкретно этот код дает эту ошибку:
No instance for (Integral Dual) arising from a use of ‘g’
In the first argument of ‘flip’, namely ‘g’
In the expression: flip g (constD c)
In the second argument of ‘($)’, namely ‘flip g (constD c) $ idD m’
Любые намеки, пожалуйста? Я уверен, что это очень пустой вопрос, но я просто не понимаю.
Полный код выглядит следующим образом:
{-# LANGUAGE NoMonomorphismRestriction #-}
module ADfw (Dual(..), f, idD, cost) where
data Dual = Dual Double Double deriving (Eq, Show)
constD :: Double -> Dual
constD x = Dual x 0
idD :: Double -> Dual
idD x = Dual x 1.0
instance Num Dual where
fromInteger n = constD $ fromInteger n
(Dual x x') + (Dual y y') = Dual (x+y) (x' + y')
(Dual x x') * (Dual y y') = Dual (x*y) (x*y' + y*x')
negate (Dual x x') = Dual (negate x) (negate x')
signum _ = undefined
abs _ = undefined
instance Fractional Dual where
fromRational p = constD $ fromRational p
recip (Dual x x') = Dual (1.0/x) (- x'/(x*x))
instance Floating Dual where
pi = constD pi
exp (Dual x x') = Dual (exp x) (x' * exp x)
log (Dual x x') = Dual (log x) (x'/x)
sqrt (Dual x x') = Dual (sqrt x) (x'/(2 * sqrt x))
sin (Dual x x') = Dual (sin x) (x' * cos x)
cos (Dual x x') = Dual (cos x) (x' * (- sin x))
sinh (Dual x x') = Dual (sinh x) (x' * cosh x)
cosh (Dual x x') = Dual (cosh x) (x' * sinh x)
asin (Dual x x') = Dual (asin x) (x'/sqrt (1 - x*x))
acos (Dual x x') = Dual (acos x) (x'/(-sqrt (1 - x*x)))
atan (Dual x x') = Dual (atan x) (x'/(1 + x*x))
asinh (Dual x x') = Dual (asinh x) (x'/sqrt (1 + x*x))
acosh (Dual x x') = Dual (acosh x) (x'/(sqrt (x*x - 1)))
atanh (Dual x x') = Dual (atanh x) (x'/(1 - x*x))
-- example
-- f = sqrt . (* 3) . sin
-- f' x = 3 * cos x/(2 * sqrt (3 * sin x))
-- linear fit sum-of-squares cost
-- cost :: Fractional s => s -> s -> [s] -> [s] -> s
cost m c x y = (/ (2 * (fromIntegral $ length x))) $
sum $ zipWith errSq x y
where
errSq xi yi = zi * zi
where
zi = yi - (m * xi + c)
-- test data
x_ = [1..10]
y_ = [a | a <- [1..20], a `mod` 2 /= 0]
-- learning rate
gamma = 0.04
g :: (Integral s, Fractional s) => s -> s -> s
g m c = cost m c x_ y_
deriv (Dual _ x') = x'
z_ = (0.1, 0.1) : map h z_
h (c, m) = (c - gamma * cd, m - gamma * md) where
cd = deriv $ g (constD m) $ idD c
md = deriv $ flip g (constD c) $ idD m
-- check for convergence
main = do
take 2 $ drop 1000 $ map (\(c, m) -> cost m c x_ y_) z_
take 2 $ drop 1000 $ z_
где x_ тестовых данных и y_ массивы и гамма скорость обучения скаляр.
[2]: Два поля дуального объекта фактически является сопряженным один с другими, если мы видим производную как оператор
Если кто-нибудь натыкается на этом примере, ошибка заключается в использовании список понимание для создания x_ данных и y_. Если вы заявляете вместо этого свои записи явно, например. x _ = [1,2,4,10,2] и т. д., It Just Works – ocramz