2016-03-29 3 views
2

Я пытаюсь установить образец фиксированного [Mx1] вектор в любые данные [Nx1] размеры с использованием метода усреднения. У меня есть динамический размер окна, который изменяется каждый раз в зависимости от требуемого массива вывода. Таким образом, в некоторых случаях мне повезло и получить размер окна int, который идеально подходит в соответствии с размером окна, и иногда я получаю плавающее число как размер окна. Но, как я могу использовать окна с плавающим размером, чтобы сделать вектор [Nx1] размер от фиксированного [Mx1] вектор?Как мы можем опробовать значения массива 1D методом усреднения с использованием размеров окна float и int?

Ниже приведен код, который я пробовал:

chunk = 0.35 
def fixed_meanVector(vec, chunk): 
    size = (vec.size*chunk) #size of output according to the chunk 
    R = (vec.size/size) #windows size to transform array into chunk size 
    pad_size = math.ceil(float(vec.size)/R)*R - vec.size 
    vec_padded = np.append(vec, np.zeros(pad_size)*np.NaN) 

    print "Org Vector: ",vec.size, "output Size: ",size, "Windows Size: ",R, "Padding size", pad_size 
    newVec = scipy.nanmean(vec_padded.reshape(-1,R), axis=1) 
    print "New Vector shape: ",newVec.shape 
    return newVec 

print "Word Mean of N values Similarity: ",cosine(fixed_meanVector(vector1, chunk) 
                 ,fixed_meanVector(vector2, chunk)) 

Выход:

New Vector shape: (200,) 
Org Vector: 400 output Size: 140.0 Windows Size: 2.85714285714 Padding size 0.0 
New Vector shape: (200,) 
0.46111661289 

В приведенном выше примере, мне нужно вниз образец [Mx1]([ 400x1]) вектор в Nx1([140x1]) размеры. Таким образом, динамически размер окна [2.857x1] может использоваться для downsample [Mx1] вектор. Но в этом случае я получаю вектор [200x1] как мой вывод вместо [140x1] из-за плавающее окно она поднимает на муки (2,85) она субдискретизация с ->[2x1] , Заполнение нуля, потому что мой размер окна идеально подходит для новых [Nx1] размеры. Итак, есть ли какой-либо способ использовать такой тип размеров окон для прогона a [Mx1] vector?

+0

Является ли число N фиксированным? – Hun

+0

@sung Нет ... Это размер вывода ... И в коде это ... size = (vec.size * chunk) –

+0

Если оба M и N не фиксированы, это немного сложно придумать очень общий алгоритм. Поскольку ваш вектор не слишком большой, я бы сказал, сделайте это итеративно. Я имею в виду, что это скользящее среднее с использованием полного целого. Затем у вас будет больший, чем требуется, дискретный вектор. Вы можете повторить процесс снова с помощью нового вектора и т. Д. – Hun

ответ

3

Возможно, но не естественным для векторизации, что, как только M%N>0. потому что количество ячеек, используемых для построения массива результатов, не является постоянным, между 3 и 4 в вашем случае.

Естественный метод для запуска через массив, настраивая на каждом бункере:

enter image description here

идея, чтобы заполнить каждый бункер до перелива. затем разрежьте перелив (перенос) и сохраните его для следующего бункера. последний перенос всегда равен нулю, используя int арифметику.

Код:

def resized(data,N): 
M=data.size 
res=empty(N,data.dtype) 
carry=0 
m=0 
for n in range(N): 
    sum = carry 
    while m*N - n*M < M : 
     sum += data[m] 
     m += 1 
    carry = (m-(n+1)*M/N)*data[m-1] 
    sum -= carry 
    res[n] = sum*N/M 
return res 

Тест:

In [5]: resized(np.ones(7),3) 
Out[5]: array([ 1., 1., 1.]) 

In [6]: %timeit resized(rand(400),140) 
    1000 loops, best of 3: 1.43 ms per loop 

Это работает, но не очень быстро. Благо, вы можете ускорить его с numba:

from numba import jit 
resized2=jit(resized)    

In [7]: %timeit resized2(rand(400),140) 
1 loops, best of 3: 8.21 µs per loop 

Вероятно, быстрее, чем любой чисто numpy решения (здесь для N=3*M):

IN [8]: %timeit rand(402).reshape(-1,3).mean(1) 
10000 loops, best of 3: 39.2 µs per loop 

Примечание это работает также, если M>N.

In [9]: resized(arange(4.),9) 
Out[9]: array([ 0. , 0. , 0.75, 1. , 1.5 , 2. , 2.25, 3. , 3. ]) 
+0

Эй, ваш метод классный! я пробовал ваш подход, и он может уменьшить векторы до любого размера. Не знаю, каково ограничение вашего подхода. Просто пытаюсь понять, как вы это делаете :) –

+0

Я добавляю некоторые объяснения, было поздно;) –

+0

Wow ,. Это отличный ответ :) .. Пожалуйста, добавьте дополнительную информацию, если это возможно. .. –

2

Вы делаете это неправильно, вы создаете окно для требуемого прореживания, а не наоборот.

Mr Nyquist говорит, что у вас не может быть BW выше fs/2, или у вас будет неприятное наложение.

Чтобы решить эту проблему, вы не просто «средний», а низкий, чтобы частоты выше fs/2 находились ниже допустимого уровня шума.

MA's являются допустимым типом фильтра нижних частот, вы просто применяете его к неправильному массиву.

Обычный чехол для arbitrary decimation есть.

Upsample -> Lowpass -> Downsample 

Таким образом, чтобы иметь возможность произвольным Decimate от N до М выборок алгоритм является:

  • найти LCM между текущими образцами ваших целевых образцов.
  • upsample по LCM/N
  • дизайна фильтра, используя стоп частоту ws<= M/LCM
  • downsample по LCM/M

То, что вы называете методом усреднения, является КИМ-фильтром с rectangular window

Если вы используете первый ноль frequency response in that window a s стоп-группа, то вы можете рассчитать необходимый размер окна K, так как

2/K <= M/LCM 

так что вы должны использовать окно размера:

ceil(2*LCM/M) = K 

Очевидно, что вам не нужно реализовывать все эти , Просто спроектируйте подходящее окно с помощью ws<= M/LCM и примените его, используя scipy.signal.resample.

И если ceil, примененный к окну, испортил ваши результаты, не используйте прямоугольные окна, есть тонны лучших фильтров, которые вы можете использовать.

+0

Хорошо. Ваш предложенный подход немного запутан для меня, потому что я думаю, что он очень применим в обработке сигналов и т. Д. Но я просто хочу сбрасывать образец массива путем усреднения. Есть ли другой метод, который лучше, чем этот подход, поделитесь. Трудно понять ваш ответ :) –

+1

Итак, как вам кажется, вам все равно, о результате, просто 'window = np.ones (ceil (float (n)/len (x)))' , 'window = window/len (window)', 'scipy.signal.resample (x, n, window = window)' – xvan

+0

Конечно, я тоже попробую этот метод :), но возможно ли уменьшить массив, сохранив фактическое значение, как в исходном векторе? –