WEB3DEV

Cover image for Inteligência Artificial na Algorand
Fernando Teixeira Barros
Fernando Teixeira Barros

Posted on • Atualizado em

Inteligência Artificial na Algorand

Visão geral

Introdução

Uma convergência de tecnologias inovadoras em big data e análise de dados fornece uma solução crítica para atingir os objetivos. Big data e análises avançadas desempenham um papel fundamental no aumento da produtividade de tarefas intensivas em conhecimento, maximizando ativos e facilitando a experiência digital personalizada.

O monitoramento preditivo de processos em tempo de execução está crescendo especialmente em importância. Prever o tempo de ciclo restante, conformidade, sequência de atividades do processo, o resultado final ou parcial ou a priorização de processos ajuda as organizações a tomar decisões e obter insights valiosos em um ambiente em rápida evolução.

Neste artigo, nos conectamos ao Algorand Indexer para acessar e coletar dados de transações do USDC usando Python. Também demonstramos a utilidade de prever o volume de transações com Machine Learning.


Sumário
Visão Geral
1 . Introdução

2 . Algorand como um banco de dados compartilhado

3 . Acessando os dados

4 . Indexador Algorand PureStake
..... . ACESSANDO O INDEXADOR
..... . CONSULTANDO TRANSAÇÕES

5 . Transformação e visualização de dados

6 . Engenharia e previsão de recursos

7 . Resultados

Conclusão


Algorand como um banco de dados compartilhado

Blockchain em sua essência é um tipo de banco de dados compartilhado que difere de um banco de dados típico na maneira como armazena informações. Uma blockchain é uma lista crescente de registros, também chamados de blocos, que são vinculados usando a mais recente tecnologia de criptografia.

Uma blockchain também é um livro de transações imutável. O primeiro bloco da cadeia é chamado de bloco Genesis. À medida que cada novo bloco ou transação é registrado, ele é adicionado ao anterior para formar uma cadeia de registros de dados ou uma blockchain. Como resultado, uma blockchain contém todas as transações registradas desde que o livro-razão foi iniciado.

Acessando os dados

Quando uma pessoa ou um aplicativo acessa os dados para fazer uma transação, na verdade está chamando nós na rede. O protocolo blockchain garante que você possa reconstruir os dados de informações recebidas de forma correta e confiável.

Todos os dados da blockchain estão na ordem de centenas de gigabytes, portanto, se você configurar seu software para armazená-lo localmente, o software normalmente baixará vários arquivos grandes de outros computadores e os armazenará em seu disco. No entanto, obter uma grande quantidade de dados filtrados e agregados diretamente de um nó levaria dias, se não semanas.

Um indexador permite explorar a blockchain de sua máquina local. Os dados vêm diretamente de um nó Algorand e podem ser acessados ​​de sua área de trabalho local com APIs de terceiros.

Para análises profundas, como a realização de pesquisas de mercado, gostaríamos de explorar históricos completos de endereços, chamadas e rastreamentos que exigem uma grande quantidade de dados. Com o indexador, podemos servir efetivamente a um aplicativo dados filtrados e agregados de forma eficiente.

Indexador Algorand PureStake

O ponto de extremidade (endpoint) mais conveniente para consultar Algorand é o PureStake Indexer que está disponível na testnet, betanet e mainnet da Algorand.

Além disso, escolhemos o Python como linguagem de programação, pois foi projetado para fazer acontecer. A sintaxe simples e organizada e o design limpo facilitam a escrita de código que simplesmente funciona. Biblioteca Python para interagir com a rede Algorand: py-algorand-sdk .

Após nos registrarmos no purestake.com para obter as chaves da API, configuramos o arquivo de configuração do ambiente para armazenar a CHAVE DE API. Em seguida, configure o cabeçalho que contém a api_key, também escolhemos o indexador mainnet purestake. Por fim, inicializamos o Algorand Indexer Client. O resultado do script deve indicar a conexão bem-sucedida e demonstrar a integridade do indexador.

ACESSANDO O INDEXADOR

Para acessar o indexador criamos um arquivo python, importamos bibliotecas e carregamos uma chave de API de ambiente.

import os
from dotenv import load_dotenv

from algosdk.v2client.indexer import IndexerClient

load_dotenv()

SECRET_KEY = os.getenv("API_KEY")

algod_header = {
    'User-Agent': 'Minimal-PyTeal-SDK-Demo/0.1',
    'X-API-Key': SECRET_KEY
}

indexer_address = "https://mainnet-algorand.api.purestake.io/idx2"

algod_indexer = IndexerClient(
    SECRET_KEY,
    indexer_address,
    algod_header
)

print(algod_indexer.health())
Enter fullscreen mode Exit fullscreen mode

CONSULTANDO TRANSAÇÕES

O script acima estendemos ainda mais para consultar os dados do USDC stablecoin , que podemos utilizar para prever o volume de mercado que aumenta significativamente a margem de manobra para liquidação na cadeia.

O USDC está disponível nativamente como Ethereum ERC-20, Algorand ASA, token Solana SPL, ativo Stellar, TRON TRC-20, token Hedera e Avalanche ERC-20.

No Algorand o asset_id do USDC é 31566704, disponível no Algorand Explorer .

No script a seguir, adicionamos a função get_data para consultar o indexador com base no período de tempo determinado, em particular, rodada inicial e final. Dentro da função, iteramos sobre a transação usando search_transactions que atendem aos critérios de pelo menos 1 unidade de valor e no limite de rodadas. Os dados são escritos em json e armazenados na pasta de dados.

import os
import json
from dotenv import load_dotenv

from algosdk.v2client.indexer import IndexerClient

load_dotenv()

SECRET_KEY = os.getenv("API_KEY")

algod_header = {
    'User-Agent': 'Minimal-PyTeal-SDK-Demo/0.1',
    'X-API-Key': SECRET_KEY
}

indexer_address = "https://mainnet-algorand.api.purestake.io/idx2"

algod_indexer = IndexerClient(
    SECRET_KEY,
    indexer_address,
    algod_header
)

def get_data(asset_id, min_round, end_round):

    reference_point = min_round
    stride = 10000
    while True:
        if end_round <= reference_point:
            break
        data = algod_indexer.search_transactions(min_round=reference_point, max_round=reference_point+stride, asset_id=asset_id, min_amount=1, limit=10000)

        len_slice = len(data['transactions'])

        else:

            file = json.dumps(data['transactions'])

            with open(f'data/json_data_{asset_id}_{reference_point}-{stride}.json', 'w') as outfile:
                outfile.write(file)

        reference_point+=10000

min_round = 11611000
max_round = 16711000
usdc = 31566704
get_data(usdc, min_round, max_round)
Enter fullscreen mode Exit fullscreen mode

Transformação e visualização de dados

Em seguida, transformamos os dados exportados e realizamos a análise exploratória dos dados.

As bibliotecas importadas:

import glob, os, json

import pandas as pd
import numpy as np

import plotly.express as px

pd.set_option('display.max_columns', 35)
pd.set_option('display.max_colwidth', None)


import warnings
warnings.filterwarnings("ignore")

from sklearn.model_selection import TimeSeriesSplit
from sklearn.ensemble import RandomForestRegressor
from sklearn.model_selection import train_test_split, GridSearchCV

from sklearn.neural_network import MLPRegressor
import sklearn.metrics as metrics
Enter fullscreen mode Exit fullscreen mode

Carregamos e concatenamos lotes de dados exportados, bem como convertemos números em formato legível por humanos.

json_dir = os.getcwd() +'/data/'

json_pattern = os.path.join(json_dir, '*.json')
file_list = glob.glob(json_pattern)

dfs = []

for file in file_list:
    with open(file) as f:
        json_data = pd.json_normalize(json.loads(f.read()))
    dfs.append(json_data)

df = pd.concat(dfs)

df.fee = df.fee / 1000000
df['asset-transfer-transaction.amount'] = df['asset-transfer-transaction.amount'] / 1000000
df['round-time'] = pd.to_datetime(df['round-time'], unit='s')
Enter fullscreen mode Exit fullscreen mode

Também agrupamos os dados por dia e somamos o valor da transação do ativo, que demonstramos com o modelo (template) plotly.

ag_df = df.groupby(by=[df['round-time'].dt.date])['asset-transfer-transaction.amount'].agg(volume='sum', mean='mean')
fig = px.line(ag_df, y=ag_df.volume, x=ag_df.index)
fig.update_layout(template="plotly_dark")
fig.show()
Enter fullscreen mode Exit fullscreen mode

Gráfico do plot

Engenharia e previsão de recursos

Também adicionamos recursos baseados em séries temporais e nos livramos de números não disponíveis:

# inserindo nova coluna com valores de ontem
ag_df.loc[:,'volume-1'] = ag_df.loc[:,'volume'].shift()

# inserindo outra coluna com a diferença entre ontem e o dia depois de consumir os valores.
ag_df.loc[:,'volume_diff'] = ag_df.loc[:,'volume'].diff()
ag_df = ag_df.dropna()
Enter fullscreen mode Exit fullscreen mode

Defina conjuntos de dados de teste e treinamento em 80%.

train = ag_df[:int(len(ag_df)*0.8)]
test = ag_df[int(len(ag_df)*0.8):]

X_train, X_test, y_train, y_test = train.drop('volume', axis=1), test.drop('volume', axis=1), train['volume'], test['volume']
Enter fullscreen mode Exit fullscreen mode

Escolhemos a rede neural embutida do sklearn e o modelo Random Forest. Também usamos o Gridsearch para comparar e configurar o melhor modelo.

model = RandomForestRegressor(random_state=42)
param_search = { 
    'n_estimators': [10, 20, 50, 100],
    'max_features': ['auto', 'sqrt', 'log2'],
    'max_depth' : [i for i in range(1,15)]
}
tscv = TimeSeriesSplit(n_splits=4)
gsearch = GridSearchCV(estimator=model, cv=tscv, param_grid=param_search, scoring = 'neg_mean_squared_error')
gsearch.fit(X_train, y_train)
rf_best_score = gsearch.best_score_
rf_best_model = gsearch.best_estimator_
print(f"{rf_best_model} at {rf_best_score}")


model = MLPRegressor(random_state=1)
param_search = { 
    'max_iter':[ 100, 200, 400, 600, 800, 1000],
    'solver': ['lbfgs', 'sgd', 'adam'],
    'activation':['identity', 'logistic', 'tanh', 'relu'],
}

tscv = TimeSeriesSplit(n_splits=4)
gsearch = GridSearchCV(estimator=model, cv=tscv, param_grid=param_search, scoring = 'neg_mean_squared_error')
gsearch.fit(X_train, y_train)
best_score = gsearch.best_score_
best_model = gsearch.best_estimator_
print(f"{best_model} at {best_score}")
Enter fullscreen mode Exit fullscreen mode

Resultados

A função de pontuação:

def regression_results(y_true, y_pred):
    # Métricas de regressão
    explained_variance = metrics.explained_variance_score(y_true, y_pred)
    mean_absolute_error = metrics.mean_absolute_error(y_true, y_pred) 
    mse=metrics.mean_squared_error(y_true, y_pred) 
    mean_squared_log_error=metrics.mean_squared_log_error(y_true, y_pred)
    r2=metrics.r2_score(y_true, y_pred)

    print('explained_variance: ', round(explained_variance, 4))    
    print('mean_squared_log_error: ', round(mean_squared_log_error, 4))
    print('r2: ', round(r2, 4))
    print('MAE: ', round(mean_absolute_error, 4))
    print('MSE: ', round(mse, 4))
    print('RMSE: ', round(np.sqrt(mse), 4))
Enter fullscreen mode Exit fullscreen mode

Obteve os seguintes resultados:

Resultados do Sklearn

Conclusão

A Sklearn Neural Network superou significativamente o modelo Random Forest fora da amostra. O resultado do R-quadrado é 1 perfeito e o erro quadrático médio é próximo de zero.

Isso significa que podemos utilizar prontamente a rede neural sklearn com pequenos aprimoramentos de parâmetros para obter de forma confiável o volume das transações do USDC diariamente.

Uma das ideias é usar para configurar o indexador com um algoritmo de aprendizado de máquina rápido como complemento de um oráculo on-chain. O contrato inteligente contendo a previsão pode ajudar ainda mais seus usuários e infraestrutura.

Artigo escrito por Pavel Fedotov e traduzido por Fernando T. Barros. O original em inglês pode ser encontrado aqui.

Latest comments (0)