Ezequias Rocha, analista de sistemas e pesquisador
EzequiasRocha
Analista de Sistemas e Pesquisador no Laboratório de Sistemas de Informação (LSI/UFCG). Bacharel em Ciência da Computação pela UFCG, mestrando. Campina Grande, Paraíba.
- github
- ezequiasOR, desde out/2018
- repos
- 50 públicos
- seguidores
- 138
- commits
- ~1.110 autorais em 22 repositórios próprios
- org
- EssentIA (@EssentIA-Agents), voltada a agentes de IA
- shell
- Pop!_OS, Neovim em Lua, tmux
Pesquisa
Replicação em PyTorch de Aspect-oriented unsupervised social link inference on user trajectory data (Byun, Choi e Kim, Information Sciences, vol. 626, 2023). A pergunta do paper: dá para dizer quem é amigo de quem sem nenhum rótulo, olhando só para os check-ins?
Os dados são trajetórias do Foursquare em Nova York. Cada check-in deixa de ser um ponto no mapa e vira uma tripla aspecto-orientada: o usuário se relaciona com um POI através de um aspecto (quando, que tipo de lugar, onde). Cada aspecto tem o próprio espaço de embedding, e as relações são projetadas como em grafos de conhecimento.
check-in (usuário, POI, tempo, categoria, geo) │ ├── usuário ─┐ ├── POI │ ├── tempo ─┤ embeddings separados, 128 dim cada ├── categoria │ tempo em 168 slots semanais └── geografia ─┘ │ projeção TransH / TransR / TransD │ h⊥ + r ≈ t⊥ no hiperplano da relação │ margin loss + orthogonal loss + norm loss │ r ortogonal ao hiperplano; normas contidas ▼ espaço de usuários → pares de amizade inferidos
Variantes implementadas: ANES, ANES_GEO, ANES_GEO_YELP, ANES_GEO_Others e LBGC_v4.
Uma semana em 168 posições
O tempo não entra como timestamp. Ele é discretizado em dia × hora, 7 × 24 = 168 slots, depois de corrigir o fuso pelo offset em minutos de cada check-in. Assim "terça às 22h" e "terça às 9h" viram vetores diferentes, e o modelo aprende ritmo, não data.
Passe o mouse ou o foco por uma célula. slot = dia × 24 + hora
Amostragem negativa por busca binária
Para treinar com margin loss é preciso sortear exemplos negativos muitas vezes por época, seguindo uma distribuição não uniforme. Em vez de varrer os pesos a cada sorteio, a implementação monta a CDF uma vez e encontra o índice por busca binária.
# esboço do mecanismo, não é o código do repositório cdf = acumulada(pesos) # O(n), uma vez só def amostra_negativa(): x = random() * cdf[-1] return busca_binaria(cdf, x) # O(log n) por sorteio
| preprocessing.py | check-ins para triplas, slots de tempo, recortes | |
| ANES.py | laço de treino | |
| model.py | embeddings, projeções e variantes | 776 |
| data.py | carregamento e amostragem | |
| loss.py | margin, orthogonal e norm loss | |
| projection.py | TransH / TransR / TransD | |
| graphutils.py | utilidades de grafo | |
| utils.py | auxiliares |
- dados
- NYC_20, 40, 60, 80 e 100, com pares verdadeiros e falsos para treino, validação e teste
- treino
- lr 1e-4, distância L1, 1000 iterações
- análise
- t-SNE para inspecionar o espaço aprendido
Open source
O turbo-whisper é um ditado por voz no estilo SuperWhisper: OpenAI Whisper, 99 idiomas, PyQt6, atalho global e waveform. Funcionava, menos para quem digita em teclado brasileiro.
O apóstrofo saía como til
O texto transcrito era digitado via evdev, que injeta scancodes crus pensando em US-QWERTY. A tecla que no layout americano é o ' ocupa, no ABNT2, a posição do ~. O sistema lê a posição física com o layout brasileiro, e o caractere sai trocado.
A correção foi parar de depender de scancode quando existe uma ferramenta que digita caracteres de verdade. Wayland primeiro, X11 depois, e o caminho antigo fica como rede de segurança.
- wtype
- xdotool type
- evdev
- PyAutoGUI
- clipboard
# a cadeia de fallback, resumida def type_text(text): wayland = (os.environ.get("WAYLAND_DISPLAY") or os.environ.get("XDG_SESSION_TYPE") == "wayland") if wayland and shutil.which("wtype"): return run(["wtype", text]) if shutil.which("xdotool"): return run(["xdotool", "type", "--clearmodifiers", "--delay", delay, text]) # evdev manda scancode US-QWERTY cru: no ABNT, ' vira ~ return (evdev_type(text) or pyautogui_type(text) or clipboard_paste(text))
Reescrito para leitura; o comportamento é o do commit.
- fix: prefer xdotool/wtype over evdev for auto-typing o bug do ABNT
- feat: language selection, headless recording, clearer offline error +143 linhas em api.py, config.py, main.py
- docs: self-hosted setup notes for Pop!_OS
As notas de self-hosting documentam o setup no Pop!_OS: servidor faster-whisper em Docker com CUDA (--gpus all), modelo Systran/faster-whisper-small, porta publicada só em 127.0.0.1, cache do HuggingFace montado como volume para não baixar o modelo a cada subida, e áudio por PipeWire/PortAudio.
Projetos
Do mais recente para o mais antigo. O que muda entre eles é menos a linguagem e mais quanto da engenharia em volta do código entrou junto: lint, teste, container, deploy.
API em FastAPI com o rigor no pyproject
CRUD REST de usuários com Pydantic v2: EmailStr na validação e schemas separados por papel (UserSchema de entrada, UserPublic de saída sem senha, UserDB, UserList). Respostas com HTTPStatus e 404 tratado. Python 3.14 com Poetry, TestClient em fixture.
# pyproject.toml (trecho) [tool.ruff.lint] preview = true select = ['I', 'F', 'E', 'W', 'PL', 'PT'] [tool.taskipy.tasks] lint = 'ruff check' pre_test = 'task lint' test = 'pytest --cov=fast_zero' post_test = 'coverage html'
PL traz as regras do pylint, PT as do estilo pytest. Rodar os testes passa antes pelo lint e termina com relatório HTML de cobertura.
Next.js com Postgres de verdade, desde o primeiro endpoint
Next.js 13 falando com Postgres pelo driver pg. O banco sobe por Docker Compose a partir de infra/compose.yaml, e o primeiro endpoint, /api/v1/status, já nasce com teste de integração em Jest contra o banco rodando.
- Prettier,
.editorconfige.nvmrcpara que o ambiente seja o mesmo em qualquer máquina - versão da API no caminho da rota
- deploy contínuo na Vercel
Três apps, cada um em três plataformas
Em 2020 fiz os projetos das Semanas Omnistack e da NLW indo até o fim em todas as frentes: API em Node, front em React e app em React Native com Expo, cada um com o próprio problema técnico.
| projeto | API | web | mobile | commits |
|---|---|---|---|---|
| Ecoleta | Express + Knex (migrations e seeds) + SQLite, validação com Celebrate/Joi, upload com Multer, CORS | React + TypeScript, mapa com Leaflet/react-leaflet, upload drag-and-drop com react-dropzone | Expo, react-native-maps, expo-location, expo-mail-composer, React Navigation | 124 |
| DevRadar | Express + MongoDB/Mongoose com consultas geoespaciais, Socket.io avisando devs próximos em tempo real, API do GitHub via axios | React | Expo com mapas, localização, WebView e socket.io-client | 123 |
| be-the-hero | Express + Knex + SQLite + Celebrate, testes com Jest e Supertest, cross-env | React | React Native com Expo | 122 |
Ecoleta é um marketplace de pontos de coleta de resíduos por geolocalização; DevRadar encontra devs por proximidade e tecnologia.
- Web-Estudos844 commits de 2019 a 2025, 479 meus. JavaScript do zero (map/filter/reduce, imperativo vs declarativo), AJAX com XHR, fetch, axios e jQuery, Express, Gulp, Webpack, Vue, React, SQL relacional com joins e agregação, MongoDB com lookup.
- Python-Estudos105 commits meus. Banco de dados com consultas parametrizadas (inclusive "selecionar sem SQL injection"), CRUD, paginação com limit/offset.
- ia-ufcgQuizzes de Inteligência Artificial em Jupyter, 2022–23.
- ibdmdDatasets para BI: lojas, gerentes, vendas.
- Java, 2020Primeiros sistemas na UFCG: coisa (Controle Institucional da Situação Acadêmica), agenda-de-contatos, controle-de-alunos.
- audio-speed-controllerExtensão que acelera os áudios do WhatsApp Web (2020).
- nvim, tmuxNeovim em Lua com LSP, Telescope, Treesitter, Harpoon, Fugitive, Undotree, Trouble, Zen Mode, refactoring e cloak. nvim e tmux.
- bin2dec, casa-criativa, doeExercícios curtos, os dois últimos da MaratonaDev.
Algoritmos
Montei trilhas semanais de Aprendizado de Algoritmos com listas no vJudge e gravei vídeos resolvendo as questões para os alunos. A trilha começa em ad hoc e termina em decomposição por raiz quadrada.
- Iniciante
- ad hoc, two pointers, soma acumulada
- busca binária
- fila, heap, pilha, set, mapa
- GCD/LCM, crivo
- aritmética modular, exponenciação binária
- Avançada
- Segment Tree
- Lazy Propagation
- Square Root Decomposition, algoritmo de Mo
ATAL na UFCG
Em Análise e Técnicas de Algoritmos, soluções de Codeforces organizadas por paradigma: força bruta, backtracking, guloso, divisão e conquista, programação dinâmica e grafos com BFS e DFS.
A aula da segment tree, em miniatura
Clique em duas posições do vetor para escolher o intervalo. Os nós em âmbar cobrem o intervalo inteiro e são somados; os em ciano são visitados e divididos; o resto nem é tocado.
Log
Números contados nos 22 repositórios próprios, sem forks. Volume de código mede quanto foi escrito em cada linguagem, não quanto eu domino cada uma.
2019 ██▎ 21 2020 ██████████████████████▋ 207 2021 █████████████████████▉ 200 2022 ████████████████████████████ 256 2023 ██████████████████▊ 172 2024 █████████████████████▏ 193 2025 ██████▋ 61 2026 ▍ 3 ──────────────────────────── ───── escala linear, 28 colunas = 256 1.113
2026 são os commits do turbo-whisper, que vivem num fork.
JavaScript ████████████████████████████ 828 CSS █████████████▎ 392 HTML ███████████▏ 330 Jupyter ██████████ 294 Python ███████▌ 223 TypeScript █▉ 55 Java █▎ 36 Lua ▍ 11 Vue ▍ 11 SQL ▎ 6
JavaScript, CSS e HTML pesam pelos anos de Web-Estudos e pelos apps de 2020.
local stack = { ia_e_dados = { "Python", "PyTorch", "scikit-learn", "Pandas", "NumPy", "Jupyter", "TransH/R/D", "Whisper", "faster-whisper", }, backend = { "FastAPI", "Pydantic", "Node.js", "Express", "Next.js API routes", "Knex", "Mongoose", "Socket.io", }, frontend_e_mobile = { "TypeScript", "React", "React Native", "Expo", "Next.js", "Leaflet", "Vue", }, bancos = { "PostgreSQL", "SQLite", "MongoDB", "MySQL" }, qualidade_e_infra = { "pytest", "Jest", "Supertest", "Ruff", "Prettier", "Poetry", "Docker", "Docker Compose", "CUDA", "Vercel", "Git", }, ambiente = { "Pop!_OS", "Neovim/Lua", "tmux", "Wayland/X11", }, } return stack
- 2026
Contribuição no turbo-whisper: o fix do ABNT.
- 2025
fast_zero em FastAPI. Nova turma de algoritmos (aa).
- 2024
Replicação do ANES na pesquisa. Config de tmux.
- 2022
IA na UFCG até 2023. Neovim configurado em Lua.
- 2021
ATAL: Codeforces por paradigma.
- 2020
Java na UFCG. Semanas Omnistack (DevRadar, Be The Hero) e NLW (Ecoleta). Começo a ensinar algoritmos.
- 2019
Começo Web-Estudos e Python-Estudos.
- 2018
Conta no GitHub.
Contato
Código no GitHub, trabalho no LinkedIn, o resto nos outros dois.