from sklearn.utils import resample
zeros = dbtrain[dbtrain['ischurn'] == 0] # 9,354 non-churnersones = dbtrain[dbtrain['ischurn'] == 1] # 646 churners
zeros_undersampled = resample(zeros, replace=False, n_samples=len(ones), random_state=42)
dbtrain_balanced = pd.concat([zeros_undersampled, ones])dbtrain_balanced = dbtrain_balanced.sample(frac=1, random_state=42).reset_index(drop=True)
Nhóm khách hàng | Số lượng | Tác động đến mô hình |
---|---|---|
Churners | 646 | Đảm bảo mô hình không bỏ sót khách hàng rời đi |
Không churners | 646 | Cân bằng giúp mô hình chính xác hơn |
from fastapi import FastAPI, HTTPExceptionfrom pydantic import BaseModelfrom typing import Optionalfrom datetime import dateimport pandas as pd
app = FastAPI( title="Customer Churn Prediction", description="Production-ready ML API for customer churn prediction", version="1.0.0")
class DataVal(BaseModel): userid: Optional[int] = None city: int gender: str registeredvia: int paymentmethodid: int paymentplandays: int actualamountpaid: int isautorenew: int transactiondate: date membershipexpiredate: date
@app.post("/predict")def predict( city: int, gender: str, registeredvia: int, paymentmethodid: int, paymentplandays: int, actualamountpaid: int, isautorenew: int, transactiondate: date, membershipexpiredate: date, userid: Optional[int] = None): data = DataVal( userid=userid, city=city, gender=gender, registeredvia=registeredvia, paymentmethodid=paymentmethodid, paymentplandays=paymentplandays, actualamountpaid=actualamountpaid, isautorenew=isautorenew, transactiondate=transactiondate, membershipexpiredate=membershipexpiredate ) # Continue with validation, transformation and prediction
/docs
import jsonimport os
def valid_user(user: int): if pd.isna(user): with open("data/users.json", "r") as f: data = json.load(f) max_user = max(data) user = max_user + 1 data.append(int(user)) with open("data/users.json", "w") as f: json.dump(data, f, indent=2) return user else: with open("data/users.json", "r") as f: data = json.load(f) if user not in data: data.append(int(user)) with open("data/users.json", "w") as f: json.dump(data, f, indent=2) return user
def save_prediction(result: dict): json_path = "data/userdata.json" if os.path.exists(json_path): with open(json_path, "r") as f: json_file = json.load(f) else: json_file = {} json_file.update(result) with open(json_path, "w") as f: json.dump(json_file, f, indent=2)
import cloudpickle
# Lưu mô hình và pipelinewith open("model/model.pickle", "wb") as f: cloudpickle.dump(adaboost_model, f)
with open("model/pipe.pickle", "wb") as f: cloudpickle.dump(pipe, f)
# Tải mô hình và pipeline trong môi trường sản xuấtwith open("model/model.pickle", "rb") as f: model = cloudpickle.load(f)
with open("model/pipe.pickle", "rb") as f: pipe = cloudpickle.load(f)
┌─────────────────────┐ ┌─────────────────────┐ ┌─────────────────────┐│ Jupyter Notebook │ ─▶ │ FastAPI Service│ ─▶ │ Production Setup ││ • Data Exploration │ │ • REST API │ │ • Load Balancer ││ • Model Training │ │ • Data Validation │ │ • Auto-scaling ││ • Pipeline Dev │ │ • Error Handling │ │ • Monitoring │└─────────────────────┘ └─────────────────────┘ └─────────────────────┘ │ │ │ ▼ ▼ ▼┌────────────────┐ ┌─────────────────┐ ┌─────────────────┐│ Custom │ │ Pydantic Models │ │ JSON Storage & ││ Transformers │ │ (Input Validation) │ │ User Management │└────────────────┘ └─────────────────┘ └─────────────────┘
Mô Hình | Độ chính xác | Tình trạng sản xuất |
---|---|---|
AdaBoost | 89.08% | ✅ Sản xuất chính |
Random Forest | 87.39% | ✅ Dự phòng |
Decision Tree | 88.24% | ✅ Dễ giải thích |
Voting Classifier | 82.35% | ✅ Mô hình tập hợp |