Domain FMCG · Retail analytics
Based Doha, Qatar
Currently Sales & Data Analyst, Qnited Trading Company — since Aug 2024
Education B.Sc. Computer Science — American University of Science & Technology (AUST), 2020–2024
Languages English · Arabic · Spanish (basic)
Open to Data Scientist · Data Analyst roles — Qatar, Gulf, remote
Résumé Download PDF
Python // Power BI // Forecasting // Market share // PyTorch
Computer science graduate working as a data analyst inside an FMCG distributor. At Qnited I own the numbers for a portfolio of brands — MIMA, Oceana, KETO, OBA Pasta, McCain, Powerroot — across Qatar's retail channels: ingesting and cleaning POS and sales extracts, modelling them in Power Query and DAX, and turning them into market-share studies, demand forecasts and the reports the commercial team runs on.
Day to day that means the unglamorous fundamentals done properly — reconciling extracts that don't agree, fixing dirty keys, validating a dashboard against source before anyone trusts it, and automating whatever I had to do twice. The question underneath all of it is the one I actually care about: is this real, or is it noise? That's what pulled me toward data science, and toward building ML systems end to end — from raw audio to a deployed model with a paper behind it.
Half Colombian, half Lebanese, based in Doha. Off the clock: space, physics, hiking, nature, reading.
Deep learning · research
ASCA v2 — reading keystrokes from sound
An acoustic side-channel attack, rebuilt end to end. A CNN + BiLSTM (2.6M parameters) classifies individual keypresses from their audio signature, then a GPT-2 word-level layer corrects the raw predictions into real words and sentences. Trained on the JBFH keystroke dataset (36 keys, MacBook + Zoom recordings). Shipped with a FastAPI backend, a React front end that records or takes uploads, full documentation and a research paper in IEEE format.
PyTorch CNN + BiLSTM GPT-2 Librosa FastAPI React
model.py
class KeystrokeNet(nn.Module):
def __init__(self, n_keys=36 ):
super().__init__()
self.cnn = ConvStack(in_ch=1 , out_ch=128 ) # mel-spectrogram → features
self.rnn = nn.LSTM(128 , 128 , bidirectional=True , batch_first=True )
self.head = nn.Linear(256 , n_keys)
def forward(self, spec):
h, _ = self.rnn(self.cnn(spec))
return self.head(h[:, -1 ]) # one of 36 keys
# predictions → GPT-2 word-level correction → text
Market intelligence
Qatar retail market-share engine
Category share by brand across Qatar's retail market, built on external POS scan data — roughly 37,000 rows and ~1,000 products per year, two years side by side for YoY. Ingested in Power Query: type-casting, de-duplication, key normalisation (SKU and outlet names that don't match between years), and a cleanup pass for the recurring source defects — non-breaking spaces in text keys, broken named ranges. Modelled as a star schema with a date table so share and YoY deltas are DAX measures, not pasted numbers. Every brand and customer listed in full; no "all other" bucket hiding the story.
Power Query DAX Power BI Excel POS data
measures.dax
-- share of category, per brand, per period
Share % =
DIVIDE (
[Brand Sales],
CALCULATE ( [Brand Sales], REMOVEFILTERS ( Brand[Brand] ) )
)
Share Δ YoY =
[Share %] - CALCULATE ( [Share %], SAMEPERIODLASTYEAR ( 'Date'[Date] ) )
Automation · Power Automate
Automated reporting pipeline
Four recurring reports that used to be refreshed and sent by hand now run themselves. Each one is a two-workbook chain: a raw-data workbook connected directly to the ERP, and a report workbook that reads from it through pivots, XLOOKUP/VLOOKUP and live formulas. A Power Automate flow opens the raw workbook, refreshes its ERP connections, saves and closes it; then opens the report, refreshes it so every pivot and lookup picks up the new data, saves it, and sends it to the manager. Same pattern, parameterised across all four reports — nothing is pasted, nothing is hardcoded.
Power Automate Excel ERP connection Pivot tables XLOOKUP Scheduled flows
flow · report_refresh (×4)
Recurrence on schedule
Open workbook raw_data.xlsx # connected to ERP
Refresh all pull latest ERP data
Save · close
Open workbook report.xlsx # pivots · XLOOKUP · live formulas → raw
Refresh all pivots + lookups recalc against new raw
Save · close
Send email manager · report attached
-- repeated for 4 reports
The question: a brand cuts its price. Volume goes up. Was that the price — or just noise? This is the question I answer for a living, so here's the machinery behind it, live.
Below is a fake year-or-so of weekly sales for one product. You set the truth — how strongly price really moves volume, how noisy the market is, how many weeks you got to see — and I fit a line the way an analyst would and check whether that effect is provable from the data alone.
What you're looking at
Each dot is one week. Left–right: how much the price changed that week (%). Up–down: how much volume changed (%).
Solid line — the effect an analyst would find from these dots alone.
Dashed line — the true effect you set. The analyst never sees this.
Shaded band — where the true line could plausibly be, given the data. Wide band = not sure.
New sample of weeks
Uncertainty band
—
—
effect found in the data
—
chance it's just noise (p)
—
volume movement explained
How to read the numbers
Effect found The slope of the solid line: % change in volume for every 1% change in price. Compare it to the truth you set.
± uncertainty The standard error. How far the found effect could reasonably be from the real one.
Chance it's noise (p) If price truly did nothing, how often would random noise produce a pattern this strong? Under 5% and we call the effect real.
Signal ÷ noise (t) Effect divided by its uncertainty. Bigger than about 2 in either direction means the effect stands out from the noise.
Movement explained (R²) How much of the up-and-down in volume the price line accounts for. The rest is everything else.
Try this
Drag weeks down to 8. Same real effect — but now the band is huge and it's unprovable. This is why "we ran the promo two weeks and it worked" isn't evidence.
Set the true effect to 0, then hit "New sample" ten times. About one in twenty comes back "real". That's the false-positive rate you accept at p < 0.05 — and why one lucky result doesn't count.
Crank noise to 25. The band balloons and the p-value gives up. Noisy markets need far more data before you can say anything.
Under the hood: ordinary least squares fitted by hand, a Student-t test on the slope, a 95% confidence band from the standard error of the fitted mean. No libraries, all in your browser.
All
Languages
Data & BI
Visualisation
ML
Tools
Python language
DAX language · daily
Power Query M language · daily
SQL language · working
Power BI bi · daily
Excel advanced modelling
Power Automate pipelines
Pandas · NumPy data
Data modelling star schema · relationships
Data cleaning & validation reconciliation · source checks
Pivot tables · XLOOKUP excel
Matplotlib · Seaborn viz
PyTorch ml
scikit-learn ml · basics
Librosa audio
Git · GitHub tools
Jupyter tools
Flight log — credentials and coursework, newest first.
2024
Advanced Learning AlgorithmsDeepLearning.AI · Machine Learning Specialization, course 2
completed
2024
Supervised Machine Learning: Regression & ClassificationDeepLearning.AI · Machine Learning Specialization, course 1
completed
2020 – 2024
B.Sc. Computer ScienceAmerican University of Science & Technology (AUST)
completed
2022
CCNAv7: Introduction to NetworksCisco Networking Academy
completed
2022
Tableau Fundamentals & IntermediateTableau
completed