PCA с несколькими временными рядами как особенности одного экземпляра со sklearn - PullRequest
0 голосов
/ 21 сентября 2018

Я хочу применить PCA к набору данных, где у меня есть 20 временных рядов в качестве функций для одного экземпляра.У меня есть около 1000 таких экземпляров, и я ищу способ уменьшить размерность.Для каждого экземпляра у меня есть фрейм данных pandas, например:

import pandas as pd
import numpy as np
df = pd.DataFrame(data=np.random.normal(0, 1, (300, 20)))

Есть ли способ использовать sklearn.fit на всех экземплярах, каждый из которых имеет набор временных рядов в качестве пространства объектов,Я имею в виду, что я мог бы применить sklearn.fit ко всем экземплярам отдельно, но я хочу, чтобы все компоненты были одинаковыми.

Есть ли способ?Единственная не удовлетворяющая меня идея - добавить все эти серии одного экземпляра в один, чтобы у меня был один временной ряд для одного экземпляра.

Ответы [ 4 ]

0 голосов
/ 22 марта 2019

Я не считаю другие ответы удовлетворительными.Главным образом потому, что вы должны учитывать как структуру временных рядов данных, так и информацию о поперечном сечении.Вы не можете просто рассматривать функции в каждом случае как одну серию.Это неизбежно приведет к потере информации и, просто говоря, статистически неверно.

При этом если вам действительно нужно перейти на PCA, вы должны по крайней мере сохранить информацию о временных рядах:

PCA

После silgon мы преобразуем данные в массив Numpy:

# your 1000 pandas instances
instances = [pd.DataFrame(data=np.random.normal(0, 1, (300, 20))) for _ in range(1000)]
# transformation to be able to process more easily the data as a numpy array
data=np.array([d.values for d in instances]) 

Это упрощает применение PCA:

reshaped_data = data.reshape((1000*300, 20))    # create one big data panel with 20 series and 300.000 datapoints
n_comp=10                                       #choose the number of features to have after dimensionality reduction
pca = PCA(n_components=n_comp)                  #create the pca object       
pca.fit(pre_data)                               #fit it to your transformed data
transformed_data=np.empty([1000,300,n_comp])
for i in range(len(data)):
     transformed_data[i]=pca.transform(data[i])           #iteratively apply the transformation to each instance of the original dataset

Конечная форма вывода: transformed_data.shape: Out[]: (1000,300,n_comp).

PLS

Однако вы можете (и должны, на мой взгляд) строить факторы из вашей матрицы характеристикиспользуя частичные наименьшие квадраты PLS .Это также обеспечит дальнейшее уменьшение размерности.

Допустим, ваши данные имеют следующую форму.T=1000, N=300, P=20.

Тогда мы имеем y = [T, 1], X = [N, P, T].

Сейчасдовольно легко понять, что для этого нам нужно, чтобы наши матрицы были совместимыми для умножения .В нашем случае у нас будет: y = [T, 1] = [1000,1], X pca = [T, P * N] =[1000,20 * 300]

Интуитивно понятно, что мы создаем новую функцию для каждой задержки ( 299 = N-1 ) каждого из P =20 базовых функций.

Т.е. для данного экземпляра i , у нас будет что-то вроде этого:

Экземпляр i : x 1, i , x 1, i-1 , ..., x 1, ij , x 2, i, x 2, i-1 , ..., x 2, ij , ..., x P, i , x P, i-1 , ..., x P, ij с j = 1, ..., N-1 :

Сейчасреализация PLS в python довольно проста.

# your 1000 pandas instances
instances = [pd.DataFrame(data=np.random.normal(0, 1, (300, 20))) for _ in range(1000)]
# transformation to be able to process more easily the data as a numpy array
data=np.array([d.values for d in instances]) 

# reshape your data:
reshaped_data = data.reshape((1000, 20*300))

from sklearn.cross_decomposition import PLSRegression

n_comp=10
pls_obj=PLSRegression(n_components=n_comp)
factorsPLS=pls_obj.fit_transform(reshaped_data,y)[0] 
factorsPLS.shape
Out[]: (1000, n_comp)

Что делает PLS?

Чтобы упростить понимание, рассмотрим трехходовой регрессионный фильтр (рабочий документ здесь ) (3PRF).Келли и Пруитт показывают, что PLS - их особый случай. 3PRF:

(The three steps)

Где Z представляет матрицу прокси.У нас их нет, но, к счастью, Келли и Пруитт показали, что мы можем жить без них.Все, что нам нужно сделать, это убедиться, что регрессоры (наши функции) стандартизированы и запускают первые две регрессии без перехвата.При этом прокси будут выбраны автоматически.

Итак, вкратце, PLS позволяет вам

  1. Добиться дальнейшего уменьшения размерности, чем PCA.
  2. учитывает какизменчивость поперечного сечения признаков и информации о временных рядах каждого ряда при создании факторов.
0 голосов
/ 18 марта 2019

Свести 2D-объекты в 1D-функцию, а затем использовать этот новый набор функций для выполнения PCA.

Предполагая, что X удерживает целые 1000 экземпляров:

from sklearn.decomposition import PCA
X = X.reshape(1000, -1)
pca = PCA(n_components=250)
pca.fit(X)

Вы можете продолжитьулучшить производительность, передавая каждый экземпляр через LSTM, чтобы получить вектор, который суммирует весь фрейм данных в более низкоразмерное векторное представление, сгладить их, а затем использовать для выполнения PCA.

0 голосов
/ 19 марта 2019

В наборе данных есть функции на основе временных рядов.Присоединение всех рядов одного экземпляра к одному, разрушит основные свойства временных рядов.

Для сохранения свойства временного ряда после уменьшения размерности вам потребуется сгенерировать новые объекты временных рядов из существующих объектов.

data = np.random.randn(1000, 300, 20)      #instance x #timestamp x #feature
pre_data = data.reshape((1000*300, 20))    #samples               x #features
pca = PCA(n_components=5)                  #features in transformed data
pca.fit(pre_data)
instance_new = pca.transform(data[0])

Здесь пять преобразованных объектов будут генерироваться из исходных объектов при каждой отметке времени, поэтому новые функции будут иметь такую ​​же отметку времени, что и исходная отметка

0 голосов
/ 18 марта 2019

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

Пожалуйста, примите во внимание, что если у вас есть 1000 экземпляров pandasВаши данные должны быть обработаны, чтобы их было проще, чем массив.У вас будет что-то вроде следующего:

# your 1000 pandas instances
instances = [pd.DataFrame(data=np.random.normal(0, 1, (300, 20))) for _ in range(1000)]
# transformation to be able to process more easily the data as a numpy array
data=np.array([d.values for d in instances]) 

При этом давайте рассмотрим 2 разных решения.

Простое решение

При этом сказано:самое простое решение - игнорировать наличие временных рядов и просто объединить информацию для выполнения анализа PCA со всеми

import numpy as np
from sklearn.decomposition import PCA
data = np.random.randn(1000, 300, 20) # n_instances, n_steps, n_features
# combine the features and the steps, then
# you perform PCA for your 1000 instances
preprocessed = data.reshape((1000, 20*300))
pca = PCA(n_components=100)
pca.fit(preprocessed)
# test it in one sample
sample = pca.transform(preprocessed[0].reshape(1,-1))

вариацией с преобразованием Фурье

Другойрешение может быть в использовании фурье, чтобы попытаться получить больше информации из вашего временного ряда.

import numpy as np
from sklearn.decomposition import PCA
data = np.random.randn(1000, 300, 20) # n_instances, n_steps, n_features
# perform a fast fourier transform
preprocessed_1 = np.fft.fft(data,axis=1)
# combine the features and the steps, then
# you perform PCA for your 1000 instances
preprocessed_2 = preprocessed_1.reshape((1000, 20*300))
pca = PCA(n_components=100)
pca.fit(preprocessed_2)
# test it in one sample
pca.transform(preprocessed_2[0].reshape(1,-1))

Примечание: будьте осторожны, в обоих случаях я намекаю на то, что у вас всегда одинаковая длинасерия.

...