AI-based size grid optimization system
A clothing size chart isn't just S/M/L. A properly sized chart matches your audience's measurements, reduces returns, and minimizes stock of extreme sizes. AI optimizes the chart based on real customer data.
Anthropometric analysis of the audience
Purchase and Return Analysis:
Transaction + return data reveals the real distribution of audience sizes: - Returns with the comment "too small" → the buyer took a smaller size than needed - "Too big" + exchange for a smaller one → systematic grading bias - Size gaps: no sales of S and XXL, only M/L → the grid does not correspond to the market
import pandas as pd
import numpy as np
from scipy import stats
from scipy.optimize import minimize
class SizeGridOptimizer:
"""Оптимизация размерной сетки по данным транзакций и возвратов"""
def analyze_size_distribution(self, orders_df, returns_df):
"""
Анализ распределения размеров: что покупают vs. что возвращают.
"""
# Купленные размеры
purchased = orders_df.groupby('size')['order_id'].count()
purchased = purchased / purchased.sum()
# Возвраты по причине размера
size_returns = returns_df[returns_df['reason'].isin(['too_small', 'too_large'])]
return_rate_by_size = size_returns.groupby('size')['order_id'].count() / orders_df.groupby('size')['order_id'].count()
# Implied true size distribution
# Если покупают M и меняют на L → реальный размер L
exchanges = returns_df[returns_df['reason'] == 'exchange']
size_shift = exchanges.groupby(['size', 'exchanged_to_size']).size().reset_index()
size_shift.columns = ['from_size', 'to_size', 'count']
return {
'purchased_distribution': purchased.to_dict(),
'return_rate_by_size': return_rate_by_size.to_dict(),
'size_exchanges': size_shift.to_dict('records')
}
def recommend_size_grid(self, body_measurement_data, target_coverage=0.95):
"""
Рекомендация размерной сетки для охвата 95% целевой аудитории.
body_measurement_data: DataFrame с измерениями (обхват груди, талии, бёдер)
"""
key_measurements = ['chest_cm', 'waist_cm', 'hip_cm']
# Fit multivariate normal distribution
means = body_measurement_data[key_measurements].mean()
cov = body_measurement_data[key_measurements].cov()
from sklearn.mixture import GaussianMixture
# Gaussian Mixture лучше одной нормали для неоднородной аудитории
gmm = GaussianMixture(n_components=3, random_state=42)
gmm.fit(body_measurement_data[key_measurements])
# Генерировать размеры как квантили распределения
sizes = ['XS', 'S', 'M', 'L', 'XL', 'XXL']
quantiles = np.linspace(0.025, 0.975, len(sizes))
# Рекомендованные измерения для каждого размера
recommendations = {}
for i, size in enumerate(sizes):
# Ожидаемые значения в этом квантиле
samples = gmm.sample(10000)[0]
sorted_chest = np.sort(samples[:, 0])
target_measurement = sorted_chest[int(quantiles[i] * len(sorted_chest))]
recommendations[size] = {
'chest_cm': float(target_measurement),
'coverage_pct': float(quantiles[i] * 100)
}
return recommendations
3D Body Scanning and Virtual Fitting
AI size recommendation:
The user enters parameters → ML recommends a size for a specific brand/article: - Data: height, weight + optional girth → prediction of the optimal size - Personalization: taking into account the history of returns and exchanges of a specific buyer - Brand-specific models: different brands use different patterns
class SizeRecommender:
"""Персональная рекомендация размера"""
def recommend(self, user_measurements, product_id, purchase_history=None):
"""
user_measurements: {'height_cm', 'weight_kg', 'chest_cm'} (опционально)
purchase_history: прошлые размеры и возвраты пользователя
"""
# Получить характеристики продукта
product = self._get_product_specs(product_id)
brand_bias = self._get_brand_size_bias(product['brand']) # маломерит/большемерит
# Базовая рекомендация по измерениям
if 'chest_cm' in user_measurements:
base_size = self._lookup_size_chart(user_measurements['chest_cm'],
product['size_chart'])
else:
# Только рост и вес — менее точно
base_size = self._estimate_from_height_weight(
user_measurements['height_cm'],
user_measurements['weight_kg'],
product['category']
)
# Поправка на бренд
adjusted_size = self._adjust_for_brand(base_size, brand_bias)
# Поправка на историю покупок
if purchase_history:
user_bias = self._compute_user_bias(purchase_history, product['brand'])
adjusted_size = self._adjust_for_user(adjusted_size, user_bias)
confidence = 0.9 if 'chest_cm' in user_measurements else 0.7
return {'recommended_size': adjusted_size, 'confidence': confidence,
'note': f"Бренд {product['brand']}: {brand_bias}"}
Optimization of procurement by size
Size buy optimization:
Correct distribution in procurement (size ratio):
def optimize_size_buy(demand_forecast_by_size, min_order_qty, budget):
"""
Оптимизация соотношения размеров в закупке.
Минимизировать нереализованные остатки + упущенные продажи.
"""
from scipy.optimize import linprog
sizes = list(demand_forecast_by_size.keys())
demand = np.array([demand_forecast_by_size[s] for s in sizes])
price = 500 # руб/единицу (пример)
# Заказать ровно столько, сколько продастся → нет остатков, нет дефицита
# Но с ограничениями на MOQ и бюджет
total_units = budget / price
# Оптимальное распределение пропорционально прогнозу
weights = demand / demand.sum()
optimal_order = (weights * total_units).astype(int)
# Гарантировать MOQ
optimal_order = np.maximum(optimal_order, min_order_qty)
return dict(zip(sizes, optimal_order))
The result of size grid optimization: a reduction in returns by 15–25%, a reduction in the balance of extreme sizes by 30–40%.
Development time: 2-3 months for the size chart analysis system and personal size recommendation.







