Previsão da DAU usando matrizes de coorte

Um desafio em previsão dau Para um produto, é que vários grupos podem exibir diferentes taxas de retenção que variam de maneira significativa. Um exemplo óbvio disso são os usuários adquiridos de diferentes canais, mas também pode ser verdadeiro para diferentes geografias, diferentes plataformas (por exemplo, iOS vs. Android) e, com o tempo, com retenção geralmente degradando a cada coorte subsequente.

Para acomodar esse efeito, as taxas de retenção devem ser aplicadas às projeções da DAU para esses grupos, com as projeções sendo agregadas em uma previsão global. Este é o propósito de TseseuMinha Biblioteca Python de código aberto para análise de coorte de marketing. Nesta postagem, descompactarei a lógica analítica por trás de como Teseu funciona e fornecerei um exemplo de como implementá -lo no Python.

As unidades atômicas de uma previsão da DAU são: (1) os tamanhos de coorte de alguns grupos (por exemplo, o número de pessoas de algum grupo que integrou para o produto em algum período de tempo) e (2) a curva de retenção histórica para esse grupo. Cada uma dessas unidades atômicas é representada como um vetor em alguma linha do tempo. O vetor de coorte captura o número diário de usuários do grupo integrado para o produto; O vetor da curva de retenção captura as taxas históricas de retenção diária para esse grupo após a integração. Cada uma dessas linhas do tempo – a linha do tempo da coorte e a linha do tempo da curva de retenção – podem ser arbitrariamente longas e são independentes uma da outra (a linha do tempo da coorte não precisa corresponder à linha do tempo da curva de retenção). A notação usada aqui para essas unidades atômicas é:

Observe aqui que o vetor da taxa de retenção provavelmente seria gerado ajustando um modelo de retenção aos dados históricos de retenção para o grupo. Mais sobre essa ideia em este post.

Com esses componentes, é possível construir uma matriz dau para a linha do tempo de retenção \ (\ mathbf {d_r} \) que capturaria a coorte decaimento nesse período. Um lugar útil para começar é um matriz triangular superior triangular\ (\ mathbf {z} \), de tamanho \ (d_r \ times d_r \) com o vetor da taxa de retenção que executa ao longo da diagonal:

\ (\ mathbf {z} \) aqui apenas preenche uma matriz com as curvas de retenção acolchoadas com 0s à esquerda, para que a retenção do primeiro dia (o primeiro valor da curva de retenção) corra ao longo da diagonal. Em termos práticos, a retenção do primeiro dia é de 1 ou 100%, pois, tautologicamente, 100% da coorte está presente no dia da integração da coorte. Para chegar a DAU, as taxas de retenção devem ser transmitidas para uma matriz composta por tamanhos de coorte. Isso pode ser feito construindo uma matriz diagonal, \ (\ mathbf {diag} (\ mathbf {c}) \) de \ (\ mathbf {c} \):

É importante observar aqui que, para transmitir os tamanhos da coorte contra as taxas de retenção, \ (\ mathbf {diag} (\ mathbf {c}) \) deve ser de tamanho \ (d_r \ times d_r \). Portanto, se o vetor de tamanho da coorte for mais longo que o vetor da taxa de retenção, ele precisará ser truncado; Por outro lado, se for mais curto, precisa ser acolchoado com zeros. O exemplo do brinquedo acima assume que \ (d_c \) é igual a \ (d_r \), mas observe que, como afirmado anteriormente, isso não é uma restrição.

Agora, uma terceira matriz de valores da DAU, \ (\ mathbf {dau_ {d_r}} \) pode ser criada multiplicando \ (\ mathbf {z} \) e \ (\ mathbf {diag} (\ mathbf {}) \):

Isso produz uma matriz quadrada de tamanho \ (d_r \ times d_r \) (novamente, assumindo \ (d_c = d_r \)) que ajusta cada tamanho de coorte pelo seu valor de curva de retenção diária correspondente, com a retenção do dia 1 sendo 100%. Aqui, cada coluna da matriz representa um dia de calendário e cada linha captura os valores da DAU de uma coorte, acolchoada de acordo com a data de sua integração. A soma de cada coluna forneceria o DAU total naquele dia do calendário, em todas as coortes.

Embora esses sejam dados úteis e sejam uma projeção, ele captura apenas DAU ao longo da duração da linha do tempo de retenção, \ (d_r \), começando de quando a primeira coorte foi integrada. O que seria mais útil é uma previsão na linha do tempo de retenção \ (d_r \) para cada coorte; Em outras palavras, a DAU de cada coorte foi projetada para o mesmo número de dias, independentemente de quando essa coorte foi a bordo. Esta é uma matriz de coorte em faixas, que fornece uma vista do calendário da DAU por coorte.

Esta matriz tem uma forma de \ (d_c \ times (d_r + d_c-1) \), onde cada linha é a projeção completa \ (d_r \)-dau da coorte, acolchoada com um zero para cada coorte que a precedeu. Para chegar a isso, a matriz da taxa de retenção em faixas, \ (\ mathbf {z} _ \ text {Banded} \) empilhe a curva de retenção \ (d_c \) vezes, mas as pistas de cada linha \ (i \) com \ (i-1 \) zeros na esquerda e \ \ (D_r + d_c – 1 \). Para fazer isso, podemos definir um Shift-and-Pad operador \ (s^{(i)} \):

Novamente, isso resulta em uma matriz, \ (\ mathbf {z} _ \ text {band} \), de forma \ (d_c \ times (d_r + d_c – 1) \) onde cada linha \ (i \) tem \ (i – 1 \) zeroes acentuada para o leste e \ A curva de retenção de comprimento completa \ (d_r \)-da Coort é representada.

In order to derive the banded DAU matrix, \(\mathbf{DAU}_\text{banded}\), the banded retention matrix, \(\mathbf{Z}_\text{banded}\), is multiplied by \(\mathbf{c}^{\mathsf{T}}\), the Taxas de conversão transpostas vetor. Isso funciona porque \ (\ mathbf {z} _ \ text {banded} \) tem \ (d_c \) linhas:

Implementar isso no Python é direto. O cerne da implementação está abaixo (o código completo pode ser encontrado aqui).

## create the retention curve and cohort size vectors
r = np.array( ( 1, 0.75, 0.5, 0.3, 0.2, 0.15, 0.12 ) )  ## retention rates
c = np.array( ( 500, 600, 1000, 400, 350 ) )  ## cohort sizes

D_r = len( r )
D_c = len( c )
calendar_days = D_c + D_r - 1

## create the banded retention matrix, Z_banded
Z_banded = np.zeros( ( D_c, calendar_days ) ) ## shape D_c * D_c + D_r - 1
for i in range( D_c ):
    start_idx = i
    end_idx = min( i + D_r, calendar_days )
    Z_banded( i, start_idx:end_idx ) = r( :end_idx - start_idx )

## create the DAU_banded matrix and get the total DAU per calendar day
DAU_banded = ( c( :, np.newaxis ) ) * Z_banded
total_DAU = DAU_banded.sum( axis=0 )

Os valores de tamanho de retenção e coorte utilizados são arbitrários. Graphing as coortes empilhadas produz o seguinte gráfico:

É simples a imagem como esse método pode ser usado para combinar cronogramas da DAU para diferentes grupos: uma matriz para cada grupo (por exemplo, coortes por geografia, com seus tamanhos de coorte separados e taxas de retenção) podem ser construídos, com todas as matrizes empilhadas verticalmente para fornecer uma imagem do total, o global dau.

Deixe um comentário