Projects are coming soon.
This tab will collect the projects I have worked on, what each one does, and how it was built.
Estimates how long a New York green taxi ride will take from its distance, pickup and dropoff zones, hour, and weekday, trained on 69,715 cleaned trips from July 2021. Five models competed on trips they had never seen, and a feed-forward neural network fed with an out-of-fold k-nearest-neighbour prediction won, landing within 3.1 minutes of the real duration on average.
- Dataset
- NYC TLC green taxi trips, July 2021
- Rows
- 83,691 raw, 69,715 clean
- Split
- 55,774 train, 13,941 test
- Target
- Trip duration in minutes
- Features
- Distance, pickup and dropoff zone, hour, weekend
- Models tried
- Linear Regression, Random Forest, Feed-Forward Neural Network, K-Nearest Neighbour, FNN + KNN Feature
- Winner
- Neural network with out-of-fold KNN
- MAE
- 3.09 minutes
- MAPE
- 22.4%
- RMSE
- 4.50 minutes
- Stack
- R, Keras, TensorFlow, caret, randomForest, FNN
Estimates the fare of a New York taxi ride from its distance, passenger count, hour, weekend, and year, trained on 149,102 cleaned trips from 2009 to 2015. Three models competed on trips they had never seen, and a linear regression was chosen over a slightly more accurate neural network because every dollar it predicts can be explained, landing within $1.47 of the real fare on average.
- Dataset
- NYC taxi fares, 2009 to 2015
- Rows
- 200,000 raw, 149,102 clean
- Split
- 119,281 train, 29,821 test
- Target
- Fare in dollars
- Features
- Distance, passengers, hour, weekend, year
- Models tried
- Linear Regression, Feed-Forward Neural Network, K-Nearest Neighbour
- Winner
- Linear Regression
- MAE
- $1.47
- MAPE
- 18.0%
- RMSE
- $2.08
- Stack
- R, Keras, TensorFlow, FNN
Flags telecom customers who are about to cancel from their contract, tenure, charges, and services, on the IBM Telco dataset of 7,032 customers. A random forest tuned with repeated cross validation, upsampling inside every fold, catches 76% of churners among customers it has never seen, with an AUC of 0.85.
- Dataset
- IBM Telco Customer Churn
- Rows
- 7,032 customers, 1,869 churned
- Split
- 5,978 train, 1,054 test
- Target
- Churn, yes or no
- Features
- 18 customer attributes
- Models tried
- Random Forest, Tuned Random Forest
- Winner
- Tuned Random Forest
- Sensitivity
- 76%
- Specificity
- 78%
- AUC
- 0.847
- Top driver
- Tenure
- Stack
- R, caret, randomForest, pROC
Flags the near-Earth asteroids NASA would call potentially hazardous from their orbit, size, and close approach, on 4,687 close approaches of 3,692 asteroids. Split by asteroid so none is graded on a pass it has already seen, a random forest catches 118 of the 121 hazardous close approaches in the test set. It is learning NASA's own two-threshold rule back, and that rule alone catches 121.
- Dataset
- NASA near-Earth object close approaches
- Rows
- 4,687 close approaches of 3,692 asteroids
- Split
- 3,139 train, 553 test asteroids
- Target
- Hazardous, yes or no
- Features
- 32 orbit, size, and approach attributes
- Models tried
- Naive Bayes, Logistic Regression, Random Forest
- Winner
- Random Forest
- Sensitivity
- 97.5%
- Specificity
- 99.8%
- AUC
- 1.000
- Top driver
- Minimum orbit intersection
- Stack
- R, caret, randomForest, e1071, pROC
Flags companies that are about to go bankrupt from their financial ratios, on the Taiwan company bankruptcy dataset of 6,819 companies. A k-nearest neighbours model on principal components, with the split made before any upsampling or PCA, catches 91% of the bankruptcies among companies it has never seen, with an AUC of 0.92.
- Dataset
- Taiwan company bankruptcy
- Rows
- 6,819 companies, 220 bankrupt
- Split
- 5,456 train, 1,363 test
- Target
- Bankrupt, yes or no
- Features
- 93 financial ratios, 49 principal components
- Models tried
- Logistic Regression, KNN
- Winner
- KNN
- Sensitivity
- 91%
- Specificity
- 80%
- Precision
- 13%
- AUC
- 0.917
- Stack
- R, caret, FactoMineR, class, pROC
Flags fake news articles from their title and text, on the Kaggle Fake and Real News dataset of 39,105 unique articles. A naive Bayes classifier over 4,537 terms, trained after removing duplicates, the Reuters dateline, and scraping artifacts, catches 94% of the fake articles it has never seen, with an AUC of 0.98.
- Dataset
- Kaggle Fake and Real News
- Rows
- 39,105 unique articles, 17,908 fake
- Split
- 31,285 train, 7,820 test
- Target
- Fake or real
- Features
- 4,537 term flags
- Model
- Naive Bayes
- Accuracy
- 95%
- Sensitivity
- 94%
- Specificity
- 96%
- AUC
- 0.984
- Top signal
- Getty Images photo credits
- Stack
- R, tm, e1071, caret, pROC
Wrote my first R programs in RStudio and R Markdown, from data types and coercion to vectors, factors, matrices, lists, and data frames. Cleaned and subset a retail sales dataset, then summarized it with table, prop.table, xtabs, and aggregate to answer business questions.
Learned the statistics every later model stands on: central tendency, spread, covariance, and correlation, the normal distribution with its density and mass functions, confidence intervals, and hypothesis testing with p-values and t-tests, all on real retail data.
Built charts in R with base graphics and the grammar of graphics in ggplot2, from exploratory boxplots to multivariate plots, custom themes, and Leaflet maps. Practiced on YouTube trending videos and Kiva loans, then shipped a Superstore sales analysis as my learn-by-building project.
Turned static ggplot2 charts into interactive plotly charts and published them as flexdashboard and Shiny web dashboards. Built two of my own: a GoFood Pontianak dashboard that ranks merchant categories, top merchants, order hours, and customers by age and district, and a Superstore dashboard that tracks orders, sales, and profit by year, category, segment, and region.
Modeled continuous targets with least squares, from simple to multiple linear regression, and selected features with backward, forward, and both-direction step-wise regression. Validated every model against its assumptions with residual plots, homoscedasticity and normality checks, and VIF for multicollinearity, then used it to estimate Gojek ride durations.
Built classifiers with logistic regression, reading them through log of odds, and with k-nearest neighbors, tuning k and rescaling features. Modeled credit risk on 2017 loans, diagnosed breast cancer from cell measurements, wrote k-NN from scratch to segment wholesale customers, and judged models by sensitivity, specificity, and precision instead of accuracy alone.
Went deeper with Naive Bayes, decision trees, and random forests, including a spam filter built with text mining, ROC curves and AUC, pruning, and k-fold cross validation. Closed the academy with a capstone that predicts driver shortages for a ride sharing service by area, hour, and weekday, where my decision tree scored 82% accuracy and 89% recall on the hidden test set and was explained with LIME.
Reduced dimensions with PCA on NYC property sales, visualized loan defaults with FactoMineR, rebuilt faces as eigenfaces, and used PCA to flag anomalies. Clustered whiskies into recommendations with k-means, then combined PCA with k-means to cluster high-dimensional data.
Broke time series into trend, seasonality, and residuals, then forecasted them with simple moving averages, exponential smoothing, Holt-Winters, and seasonal ARIMA. Made series stationary with differencing and validated every model's residuals with ACF, PACF, and the Ljung-Box test.
Built neural networks from first principles, working through cost functions, backpropagation, and gradient descent, then moved to Keras with dense layers and the SGD, RMSprop, and Adam optimizers. Predicted the success of a bank telemarketing campaign and classified handwritten digits from MNIST.
Picked up Python for analytics with pandas, from data types and categorical conversion to indexing, conditional subsetting, and referencing versus copying DataFrames. Practiced on supermarket rice receipts and company sales records.
Explored household purchase receipts in pandas by parsing datetimes and categories, summarizing them with crosstabs, aggregation tables, and pivot tables, and treating missing values and duplicates before drawing any conclusion.
Reshaped data with stack, unstack, and melt, aggregated it with groupby and agg, and visualized it with pandas and Matplotlib. Compared the growth and volatility of Apple, Google, and Tesla stock, and kept every analysis reproducible with pinned requirements.
Queried a relational music store database from Python with SELECT, JOIN, GROUP BY, and WHERE, then moved the results into pandas for analysis. The capstone was a Flask API over an Austin bike sharing database that records stations and trips and serves insights like the busiest stations.
Ran the full scikit-learn workflow, from EDA, outlier handling, encoding, and standardization to train-test splitting. Predicted bank customer churn with a support vector classifier, priced diamonds with support vector regression, and tuned C, kernel, gamma, and epsilon to improve both.
Forecasted daily sales of 1C Company, one of the largest Russian software firms, across 2.9 million records with Prophet. Modeled trend, seasonality, and holiday effects, evaluated forecasts with a train-test split and expanding window cross validation, and tuned hyperparameters to improve them.