kaatib-1404 / app.py
HosseinAhmadi's picture
Update app.py
3e5f9cf verified
# کاتب v8 – نسخه نهایی بدون لیکیج و با دقت واقعی بازار تهران ۱۴۰۴
import pandas as pd
import numpy as np
from catboost import CatBoostRegressor
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_absolute_error
import pickle
print("کاتب v8 در حال ساخت — این بار بدون هیچ اشتباهی! 🔥")
df = pd.read_csv("/kaggle/input/divar-dataset-2024/real_estate_ads.csv")
df = df[(df['cat3_slug'] == 'apartment-sell') & (df['city_slug'] == 'tehran')].copy()
# پیش‌پردازش پاک و بدون لیکیج
df = df.rename(columns={
'price_value': 'price', 'building_size': 'area', 'rooms_count': 'rooms_raw',
'neighborhood_slug': 'neighborhood', 'construction_year': 'year',
'has_elevator': 'elevator', 'has_parking': 'parking', 'has_warehouse': 'warehouse'
})
df = df.dropna(subset=['price', 'area'])
df['price'] = pd.to_numeric(df['price'], errors='coerce')
df['area'] = pd.to_numeric(df['area'], errors='coerce')
df = df.dropna(subset=['price', 'area'])
# فیلترهای منطقی (واقعی بازار)
df = df[(df['price'] > 800_000_000) & (df['price'] < 150_000_000_000)]
df = df[(df['area'] > 40) & (df['area'] < 500)]
# فیکس اتاق
def fix_rooms(x):
if pd.isna(x): return 2
x = str(x).lower()
if x.isdigit(): return int(x)
nums = {'یک':1,'دو':2,'سه':3,'چهار':4,'پنج':5,'شش':6,'هفت':7,'هشت':8}
for k,v in nums.items():
if k in x: return v
return 2
df['rooms'] = df['rooms_raw'].apply(fix_rooms) if 'rooms_raw' in df.columns else 2
df['rooms'] = df['rooms'].astype(int)
# فیچرهای پاک (بدون price_per_m2!)
df['year'] = pd.to_numeric(df['year'], errors='coerce')
df['age'] = 1404 - df['year'].fillna(1398)
df['is_new'] = (df['age'] <= 5).astype(int)
df['log_area'] = np.log1p(df['area']) # لگاریتم متراژ کمک می‌کنه
df['neighborhood'] = df['neighborhood'].fillna('نامشخص').astype(str)
# امکانات
for col in ['elevator', 'parking', 'warehouse']:
if col in df.columns:
df[col] = df[col].fillna(False).astype(bool)
else:
df[col] = False
print(f"دیتاست نهایی v8: {len(df):,} آگهی پاک و بدون لیکیج")
# فقط فیچرهای مجاز (هیچ اطلاعاتی از قیمت در ورودی نیست!)
features = ['area', 'log_area', 'rooms', 'age', 'is_new', 'neighborhood', 'elevator', 'parking', 'warehouse']
X = df[features]
y = df['price']
X_train, X_val, y_train, y_val = train_test_split(X, y, test_size=0.2, random_state=42)
model_v8 = CatBoostRegressor(
iterations=8000,
depth=10,
learning_rate=0.03,
loss_function='RMSE',
verbose=500,
cat_features=['neighborhood'],
random_seed=42,
early_stopping_rounds=500
)
print("آموزش کاتب v8 شروع شد...")
model_v8.fit(X_train, y_train, eval_set=(X_val, y_val))
# تست واقعی روی آگهی پونک (۶۸ متر مفید، ۲ خواب، پونک، فول امکانات، حدود ۱۰ سال ساخت)
test = pd.DataFrame([{
'area': 68,
'log_area': np.log1p(68),
'rooms': 2,
'age': 10,
'is_new': 0,
'neighborhood': 'پونک',
'elevator': True,
'parking': True,
'warehouse': True
}])
pred = model_v8.predict(test)[0] / 1_000_000_000
print(f"\nپیش‌بینی کاتب v8 (۶۸ متر مفید - پونک - فول): {pred:.2f} میلیارد تومان")
print(f"قیمت واقعی آگهی: 9.98 میلیارد → خطا: {abs(pred - 9.98):.2f} میلیارد")
# ارزیابی کلی
val_pred = model_v8.predict(X_val)
mae = mean_absolute_error(y_val, val_pred) / 1e9
print(f"\nمیانگین خطا کلی (MAE): ±{mae:.2f} میلیارد تومان")
# ذخیره مدل نهایی
with open("kaatib_v8_best.pkl", "wb") as f:
pickle.dump(model_v8, f)
print("\nکاتب v8 آماده است — این بار واقعاً دقیق و بدون تقلب!")