Classificação de séries temporais para introdução ao Pyts --- Introdução ao algoritmo TimeSeriesForest (5)

Introdução

O algoritmo de classificação de séries temporais está chegando ao fim. Esta seção apresentará o algoritmo TimeSeriesForest, ou seja, o algoritmo de floresta aleatória aplicado às séries temporais. Ao mesmo tempo, a próxima seção e a última seção apresentarão o algoritmo TSBF baseado nele. Antes de estudar esta seção, você precisa atualizar o Pyts para a versão mais recente (0.12.0 quando este artigo foi publicado), porque 0.11.0 (a versão que instalei em outubro passado) não possui esses dois algoritmos:

pip install --upgrade pyts

As etapas do algoritmo de TimeSeriesForest são divididas nas duas etapas a seguir:
1. Extrair três recursos de uma série de sequências de janelas aleatórias: média, desvio padrão e inclinação da regressão linear simples.
2. Insira esses três recursos na floresta aleatória para treinamento.

Portanto, o foco está na primeira etapa. A segunda etapa é na verdade uma floresta aleatória comum. Não é tanto um novo algoritmo para séries temporais, mas um novo método de extração de recursos. Antes de apresentar como selecionar a sequência de janelas, vamos explicar primeiro a API, como de costume.

API

class pyts.classification.TimeSeriesForest(n_estimators=500, 
n_windows=1.0, min_window_size=1, criterion='entropy', 
max_depth=None, min_samples_split=2, min_samples_leaf=1, 
min_weight_fraction_leaf=0.0, max_features='auto', 
max_leaf_nodes=None, min_impurity_decrease=0.0, bootstrap=True, 
oob_score=False, n_jobs=None, random_state=None, verbose=0, 
class_weight=None, ccp_alpha=0.0, max_samples=None)

Comparado com o RandomForestClassifier do sklearn (1.0.2), há mais dois parâmetros, n_windows e min_window_size, e o parâmetro warm_start está ausente.

parâmetro ilustrar
n_estimadores int, o número de árvores na floresta, muitas são fáceis de superajustar, poucas são fáceis de não ter informações
n_windows int ou float, o número de janelas para extração de recursos, quanto mais janelas, mais recursos
min_window_size int ou float, o comprimento mínimo da janela, se for um decimal, é o comprimento da sequência multiplicado por este valor
critério "gini" ou "entropia", diretrizes para particionamento de nós
profundidade máxima int ou None, o limite de profundidade da árvore não pode ser definido, mas é fácil sobreajustar
min_samples_split int ou float, o número mínimo de amostras a serem incluídas na divisão de nós internos (nós que podem continuar a separar nós), se for float, será arredondado para cima (min_samples_split * número de amostras)
min_samples_leaf int ou float, o número mínimo de amostras contidas no nó folha, se for float, será arredondado para cima (min_samples_leaf * número de amostras), pode ser possível suavizar o modelo
min_weight_fraction_leaf float, a pontuação mínima de peso para se tornar um nó folha, quando o parâmetro sample_weight não é fornecido quando ajustado, todas as amostras têm o mesmo peso
max_features int, float, str ou None, geralmente "auto", o número máximo de recursos considerados na divisão. Se for float, então max_features=round(max_features * n_features), se for "auto" ou "sqrt", max_features=sqrt(n_features), se for "log2", max_features=log2(n_features), se for None, max_features=n_features.
max_leaf_nodes int, número máximo de nós folha
min_impurity_decrease float, a redução mínima de impurezas, um nó será dividido somente quando a redução de impurezas da divisão for maior ou igual a este valor
bootstrap bool, se deve usar o método boostrap para construir cada árvore, se False, todo o conjunto de amostra será usado.
oob_score bool, se deve usar pontuações out-of-bag para pontuação, somente quando bootstrap for True, haverá algumas amostras que nunca foram sorteadas para pontuação
n_empregos int ou None, o número de threads, quando -1 todos estiverem esgotados
estado_aleatório int, instância RandomState ou None, semente aleatória, afetando dois processos: 1.bootstrap, 2. Encontrando o ponto de divisão.
prolixo int, exibição de informações de controle
peso_classe dict, "balanced", "balanced_subsample" ou None, adicione peso à categoria, use n_samples / (n_classes * np.bincount(y)) quando "balanced", quando for "balanced_subsample", o mesmo cálculo, apenas use a amostra bootstrap quando cada árvore for construída
ccp_alpha Decimal não negativo, o parâmetro de complexidade do algoritmo de corte de complexidade de custo mínimo, em resumo, é para evitar o overfitting, consulte Corte de complexidade de custo mínimo para obter detalhes
max_samples int ou float, quando boostrap=True, o número máximo de amostras usadas para caber em cada árvore, se for None, é X.shape[0], se for float, é max_samples * X.shape[0]

Explicação dos principais problemas

1. Como mencionado anteriormente, nada mais é do que adicionar um método de extração de recursos com base no RandomForest, extraindo a média, o desvio padrão e três parâmetros da inclinação da regressão linear, então é realmente melhor que o RandomForest?

from pyts.datasets import load_gunpoint
from pyts.classification import TimeSeriesForest
from sklearn.ensemble import RandomForestClassifier
X_train, X_test, y_train, y_test = load_gunpoint(return_X_y=True)
TSF = TimeSeriesForest(random_state=2)
RFC = RandomForestClassifier(n_estimators=500,criterion='entropy',random_state=2)
RFC.fit(X_train, y_train)
print(RFC.score(X_test, y_test) #0.9333333333333333
TSF.fit(X_train, y_train)
print(TSF.score(X_test, y_test) #0.9733333333333334

Para ser justo, foram usados ​​os mesmos números aleatórios com os mesmos parâmetros, e a precisão foi 0,04 pontos percentuais maior neste caso. Claro, não está descartado que seja causado por muitos recursos neste caso (150 pontos de tempo) Como em outros casos, os leitores são solicitados a testar por si mesmos.
2. Então, como é extraído, vale a pena aprender esse método de extração de recursos?
Primeiro cole um código-fonte ligeiramente modificado:

def extract_features(X, n_samples, n_windows, indices):
    X_new = np.empty((n_samples, 3 * n_windows)) #创建空序列
    for j in range(n_windows):
        start, end = indices[j] #取一个窗口的起点和终点
        arange = np.arange((start - end + 1) / 2, (end + 1 - start) / 2) #取x序列
        if end - start == 1:
            var_arange = 1.
        else:
            var_arange = np.sum(arange ** 2) #取x序列的平方和

        for i in range(n_samples):
            mean = np.mean(X[i, start:end]) #取y序列的平均值
            X_new[i, 3 * j] = mean #第一个特征为平均值
            X_new[i, 3 * j + 1] = np.std(X[i, start:end]) #第二个特征值为标准差
            X_new[i, 3 * j + 2] = (
                np.sum((X[i, start:end] - mean) * arange) / var_arange
            ) #第三个特征值为斜率

    return X_new
start = rng.randint(0, n_timestamps - min_window_size, size=n_windows) #随机窗口起点序列
end = rng.randint(start + min_window_size, n_timestamps + 1,
                          size=n_windows) #随机窗口终点序列
indices = np.c_[start, end] #将起点序列和终点序列对应拼接

Algumas pessoas podem ler os comentários e ainda não entender o que significa. Aqui está um exemplo simples. Por exemplo, temos a seguinte sequência:

X = np.array([[1, 2, 2, 1, 2, 3, 2],
     [0, 2, 0, 2, 0, 2, 3],
     [0, 1, 2, 2, 1, 2, 2]])

Conforme mencionado no capítulo anterior, neste momento n_samples=3, ou seja, contém três sequências, n_timestamps=7 e há 7 pontos no tempo. Se o parâmetro padrão n_windows=1 , ou seja, só precisamos gerar aleatoriamente uma janela, então o valor final do recurso retornado é apenas três recursos de uma janela . Se n_windows=2, existem duas janelas, ou seja, 2x3 = 6 recursos . Quando n_windows=1, randint retorna apenas um ponto devido ao tamanho=1:

start = rng.randint(0, 7 - 1, size=1)
end = rng.randint(start + 1, 7 + 1, size=1)
indices = np.c_[start, end]

insira a descrição da imagem aqui
Ou seja, selecionamos um valor em X (X[i, início:fim]) neste momento para calcular a média, desvio padrão e inclinação.
Neste momento, alguns amigos podem querer perguntar, a média, desvio padrão, estes podem ser calculados com uma função de numpy, compreensível, mas por que a inclinação é calculada dessa maneira?

np.sum((X[i, start:end] - mean) * arange) / var_arange
var_arange = np.sum(arange ** 2)

O ponto importante a ser explicado aqui é que arange é uma sequência gerada por np.arange com o mesmo comprimento da janela X. Existem vários números na janela e vários números em arange. Ou seja, aqui usamos a janela de X como a sequência y e arange como a sequência x.
Por exemplo, eu tenho a janela [4,5,6,7,8], start=3, end=8, então o intervalo gerado é [-2,-1,0,1,2]. Portanto, estamos procurando a inclinação da melhor linha de ajuste para x: [-2, -1, 0, 1, 2] e os valores y correspondentes [4, 5, 6, 7, 8
insira a descrição da imagem aqui
] .

referência

https://zhuanlan.zhihu.com/p/73494604
https://pyts.readthedocs.io/en/stable/generated/pyts.classification.TimeSeriesForest.html#pyts.classification.TimeSeriesForest

Acho que você gosta

Origin blog.csdn.net/weixin_43945848/article/details/123541609
Recomendado
Clasificación