| Component | Technology | Key Design |
|---|---|---|
| API | Spring Boot | REST endpoints, rate limiting, circuit breaker |
| Models | Weka (SVM, NB, LR, RF) | Strategy pattern, calibrated probabilities |
| Preprocessing | TF-IDF + MI selection | Thread-safe with ReadWriteLock |
| Deployment | Docker | Non-root container, health checks |
Production model: SVM trained on Amazon reviews, 88.0% cross-domain accuracy.
Training: CSV → DataLoader → TextPreprocessor.fit() → WekaInstancesConverter.fit() → Classifier.train() → Serialized model
Inference: HTTP request → Rate limiter → Circuit breaker → Classifier.classify() → Response
SimpleDatasetLoader: CSV/TSV parsing with auto-detectionDataset: Immutable data containerDataPreparer: Creates reproducible train/test splits with SHA-256 checksums
TextPreprocessor: Text cleaning, tokenization, stopword removal, MI feature selectionWekaInstancesConverter: TF-IDF vectorization via Weka filters- Thread-safe via
ReadWriteLock(concurrent reads, exclusive writes)
SentimentClassifierinterface with implementations: SVM, NaiveBayes, RandomForest, LogisticRegression- All models return calibrated probabilities (Platt scaling for SVM)
ClassifierEvaluationResult: Accuracy, F1, precision, recall, ROC-AUCCalibrationMetrics: Brier Score, ECECrossDomainEvaluator: Tests generalization across IMDB, Amazon, Yelp
SentimentController: REST endpointsPredictionMetrics: Production monitoring via Micrometer
Endpoints:
POST /api/v1/sentiment/analyze- Single classificationPOST /api/v1/sentiment/batch- Batch classificationGET /api/v1/model/feature-importance- Top featuresGET /api/v1/health- Health check
ModelTrainer: Offline training with cross-validation
private final ReadWriteLock lock = new ReentrantReadWriteLock();
public void fit(List<Dataset> datasets) {
lock.writeLock().lock();
try { /* modify state */ }
finally { lock.writeLock().unlock(); }
}
public Instances transform(List<Dataset> datasets) {
lock.readLock().lock();
try { /* read-only access */ }
finally { lock.readLock().unlock(); }
}Weka's SMO with -V -1 enables Platt scaling to convert SVM outputs to calibrated probabilities.
@CircuitBreaker(name = "modelInference", fallbackMethod = "classifyTextFallback")
private ResponseEntity<SentimentResponse> classifyText(String text, Double threshold) { ... }Configuration: Opens after 50% failure rate, waits 30s before retry.
resilience4j.ratelimiter.instances.sentimentApi:
limit-for-period: 100
limit-refresh-period: 1m| Decision | Choice | Rationale |
|---|---|---|
| ML Library | Weka | Mature, interpretable, low resource usage |
| Framework | Spring Boot | Ecosystem, monitoring, configuration |
| Classification | Binary only | Higher accuracy, clearer evaluation |
| Feature Selection | Mutual Information | No distributional assumptions, captures non-linear relationships |
| Models | Pre-trained | Fast startup for container orchestration |
- Weka: https://waikato.github.io/weka-wiki/
- Spring Boot: https://docs.spring.io/spring-boot/docs/current/reference/html/
- Platt Scaling: Platt, J. (1999). "Probabilistic Outputs for Support Vector Machines"