2016-11-06 3 views
4

평균 :이동 무게의 목록을 감안할 때 하스켈

let weights = [0.1, 0.2, 0.4, 0.2, 0.1] 

및 측정의 배열, 나는 가중 평균을 구현하고자합니다.

이것은 내가 파이썬에서 어떻게 할 것입니다 :

y=[] 
w = length(weights) 
for n in range(w,len(x)-w): 
    y[n-w/2-1]=sum([a*b for a,b in zip(weights,x[n-w/2:n+w/2+1])]) 
    #y[n-3]=W[1]*x[n-2]+W[2]*x[n-1]+W[3]*x[n]+W[4]*x[n+1]+W[5]*x[n+2] 

나는 내가 무엇을 달성하기 위해 노력하고있어 내가 수동으로 가중치를 정의 할 수있는 low-pass-filter이며, 하스켈은 배열이없는 것을 알고있다.

+0

일부 마술을 감안할 때, 나는 조랑말을 원합니다. 그러나 진지하게, 그것은 horrendously underspecified입니다. 'x' 란 무엇입니까? 'w'는 무엇입니까 (아마도'무게'를 의미합니까?)? '길이 w'는 항상 '5'입니까? 다른 언어로 참조 구현이 있습니까? __ 대체 뭘 먹었 니? – Zeta

+0

X는 입력 배열, w는 가중치, y는 결과 배열입니다. –

+0

우리는 배열이없는 언어를 사용하므로 언어 ​​초보자라고 가정합니다. 어느 쪽이든, 추가 정보는 질문 자체에 포함되어야합니다. 다른 사용자는 주석에서 정보를 제거 할 필요가 없습니다. 나는 완전한 대답을 줄 시간이 없지만, 이것은 '꼬리 (tails)', 'zipWith (zipWith)'및 약간의 경계 동작을 통해 실현 가능해야합니다. – Zeta

답변

2

tails은 입력 목록의 꼬리 목록을 제공합니다. 그래서 tails [1,2,3] = [[1,2,3],[2,3],[3],[]]. 마지막 비어있는리스트가 필요 없으므로, 마지막 요소를 제외한 꼬리 목록의 모든 것을 얻기 위해 (init.tails)을 사용합니다.

import Data.List (tails) 
averages :: Num a => [a] -> [a] -> [a] 
averages weights xs = sum . zipWith (*) weights <$> (init.tails) xs 

목록의 시작과 끝 부분에서 원하는대로 작동하지 않을 가능성이 높습니다. 특히 시작과 끝에서 다르게 행동하기 때문에 특히 그렇습니다. 첫 번째 요소는 첫 번째 length weight 요소의 평균이되지만 마지막 요소는 head weight * last xs이됩니다.

당신이 시작의 끝의 동작을 원하는 경우는 다음과 같이 사용할 수 있습니다

import Data.List (tails) 
averages :: Num a => [a] -> [a] -> [a] 
averages weights xs = sum . zipWith (*) weights <$> 
    takeWhile (not . null . drop (l-1)) (tails xs) 
    where l = length weights 
: 당신이 시작의 끝의 행동이 당신이 사용하려는 경우

import Data.List (tails) 
averages :: Num a => [a] -> [a] -> [a] 
averages weights xs = sum . zipWith (*) weights <$> 
    (init.tails) (replicate (length weights - 1) 0 ++ xs) 

import Data.List (tails) 
averages :: Num a => [a] -> [a] -> [a] 
averages weights xs = sum . zipWith (*) weights <$> 
    takeWhile (not . null . drop half) (replicate half 0 ++ xs) 
    where half = length weights `quot` 2 
:

시작하고 첫 번째/마지막 요소로 종료 할 경우 우리가 위의 두 답변의 조합을 사용해야 가중치 목록의 중심 요소와 곱되고

+2

'takeWhile (> = 길이 가중치)'는 리소스에 매우 친숙하지 않습니다. 대신에,'l = length weights'를 한 번 사용한 다음''not ''를 사용하십시오. 없는 . drop (l - 1)'을 사용하여 목록에 적어도 "l"요소가 있는지 확인하십시오. – Zeta

3

이동 평균은 밀리 머신으로 계산할 수 있습니다. 여기서 내부 상태는 이전 값입니다.

예를 들어 3 개 이상의 인수를 이동 평균으로 표시 할 수 있습니다. 크기가 매개 변수화되도록하십시오.

Mealy i o ~ (s, s -> i -> (o, s)) 

가의 초기 상태는 모두 0이라고 가정하자, 평균 이동 함수를 작성 :

반점이 기계는 "상태 + 입력", "새로운 상태 + 출력"기능은 본질적으로 초기 상태이며,

runMealy :: (S -> I -> (O, S)) -> S -> [I] -> [O] 
runMealy _ _ [] = [] 
runMealy f s (x : xs) = 
    let (o, s') = f s x 
    in o : runMealy f s' xs 
,369 3. 이제

type S = (Double, Double) 
type I = Double 
type O = Double 

initialState :: S 
initialState = (0, 0) 

weight0, weight1, weight2 :: Double 
weight0 = 0.25 
weight1 = 0.5 
weight2 = 0.25 

ma :: S -> I -> (O, S) 
ma (x0, x1) x2 = (o, s) 
    where 
    s = (x1, x2) 
    o = x0 * weight0 + x1 * weight1 + x2 * weight2 

을 통해 우리는 모든 조각,의 입력에 기계를 실행 할 수있어

그리고 그것을 시도 :

λ *Main > runMealy ma initialState [1,2,3,4,5,6,7,8,9] 
[0.25,1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0] 

할 수 있습니다 기계 내부 상태가 "워밍업"있는 그대로, 처음 생산 된 값을 놓습니다.임의 들어


는 한쪽에 밀어 때, 더 나은 데이터 구조입니다, 당신은, Data.Sequence를 사용할 수 평균 기계를 이동 크기를 서로 팝, 다음 단일 연결리스트, [] 동안.


왜 Mealy 컴퓨터에 대해 이야기하고 있습니까? 어느 시점에서 하스켈에서 스트리밍 라이브러리를 사용해야하는 경우가 가장 많습니다 : pipes, conduit 또는 machines. 그런 다음 Mealy 시스템 접근 방식 만이 유일한 합리적인 솔루션입니다.

또한 자동 회귀 모델을 만들 수 있습니다!

+0

"Mealy 머신 접근 방식 만이 유일한 합리적인 해결책이 될 것입니다."- 그것은 매우 강력한 주장입니다. 레퍼런스가 있으십니까? – user3237465

+0

@ user3237465 시간에 단일 입력 요소를 처리하도록 제한하는 경우 Mealy 컴퓨터와 같은 것으로 끝납니다. 당신을 위해 움직이는 버퍼를 만드는 몇 가지 조합자가 있을지 모르지만 그것은 Mealy 기계입니다. – phadej

3

을 압축은 자동적으로 배향 처리한다 :

wma :: Num a => [a] -> [a] -> [a] 
wma weights = map (sum . zipWith (*) weights) -- weighted-moving-average 
       . foldr (zipWith (:)) (repeat []) 
       . take (length weights) 
       . tails 

(see also).