关于 predictive-analytics-construction
面向施工团队的机器学习技能,利用历史项目数据预测成本超支、进度延误、质量问题和风险,为预警与规划提供依据。
主要功能
- 01预测成本超支
- 02预测进度延误
- 03预测质量问题
- 04识别项目风险
- 05辅助资源规划
- 06利用历史数据改进估算
适用场景
- 01标记可能超预算的项目
- 02提前识别可能的进度延误
- 03优先关注高风险项目领域
- 04依据预测需求规划资源
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ datadrivenconstruction/ ddc_skills_for_ai_agents_in_construction --skill predictive-analytics-construction安装后在 Claude Code 中输入/predictive-analytics-construction确认已加载。
附带文件claw.jsoninstructions.md
详细介绍
建筑业预测分析
概述
利用历史项目数据预测未来结果:成本超支、工期延误、质量问题和风险。应用针对建筑行业模式定制的机器学习模型。
商业价值
预测分析有助于主动管理项目:
- 提前预警:在项目发生超支前识别可能超支的项目
- 资源优化:根据预测需求分配资源
- 风险缓解:尽早关注高风险领域
- 改进估算:从历史准确性中学习
技术实现
from dataclasses import dataclass, field
from typing import List, Dict, Any, Optional, Tuple
import pandas as pd
import numpy as np
from datetime import datetime
from sklearn.ensemble import RandomForestRegressor, GradientBoostingClassifier
from sklearn.preprocessing import StandardScaler, LabelEncoder
from sklearn.model_selection import train_test_split, cross_val_score
from sklearn.metrics import mean_absolute_error, accuracy_score, classification_report
import warnings
warnings.filterwarnings('ignore')
@dataclass
class PredictionResult:
prediction: float
confidence: float
prediction_type: str
features_used: List[str]
feature_importance: Dict[str, float]
comparable_projects: List[str]
risk_factors: List[str]
@dataclass
class ModelMetrics:
model_name: str
accuracy: float
mae: float
feature_importance: Dict[str, float]
training_samples: int
last_trained: datetime
class ConstructionPredictiveAnalytics:
"""Predictive analytics for construction projects."""
def __init__(self):
self.models: Dict[str, Any] = {}
self.scalers: Dict[str, StandardScaler] = {}
self.encoders: Dict[str, LabelEncoder] = {}
self.metrics: Dict[str, ModelMetrics] = {}
self.feature_columns: Dict[str, List[str]] = {}
def prepare_features(self, df: pd.DataFrame, target_col: str) -> Tuple[pd.DataFrame, pd.Series]:
"""Prepare features for model training."""
# Separate numeric and categorical columns
numeric_cols = df.select_dtypes(include=[np.number]).columns.tolist()
categorical_cols = df.select_dtypes(include=['object', 'category']).columns.tolist()
# Remove target from features
if target_col in numeric_cols:
numeric_cols.remove(target_col)
if target_col in categorical_cols:
categorical_cols.remove(target_col)
# Encode categorical variables
df_encoded = df.copy()
for col in categorical_cols:
if col not in self.encoders:
self.encoders[col] = LabelEncoder()
df_encoded[col] = self.encoders[col].fit_transform(df[col].astype(str))
else:
df_encoded[col] = self.encoders[col].transform(df[col].astype(str))
feature_cols = numeric_cols + categorical_cols
X = df_encoded[feature_cols].fillna(0)
y = df[target_col]
return X, y, feature_cols
def train_cost_overrun_model(self, historical_data: pd.DataFrame) -> ModelMetrics:
"""Train model to predict cost overrun percentage."""
# Expected columns: project_type, original_estimate, gross_area, duration_months,
# num_change_orders, complexity_score, contractor_experience, final_cost
required_cols = ['original_estimate', 'final_cost']
if not all(col in historical_data.columns for col in required_cols):
raise ValueError(f"Missing required columns: {required_cols}")
# Calculate overrun percentage
df = historical_data.copy()
df['overrun_pct'] = ((df['final_cost'] - df['original_estimate']) / df['original_estimate']) * 100
# Prepare features
feature_cols = [col for col in df.columns if col not in ['final_cost', 'overrun_pct', 'project_id', 'project_name']]
X, y, used_features = self.prepare_features(df[feature_cols + ['overrun_pct']], 'overrun_pct')
# Split data
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# Scale features
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)
# Train model
model = GradientBoostingRegressor(n_estimators=100, max_depth=5, random_state=42)
model.fit(X_train_scaled, y_train)
# Evaluate
y_pred = model.predict(X_test_scaled)
mae = mean_absolute_error(y_test, y_pred)
# Cross-validation
cv_scores = cross_val_score(model, X_train_scaled, y_train, cv=5, scoring='neg_mean_absolute_error')
# Feature importance
importance = dict(zip(used_features, model.feature_importances_))
# Store model
self.models['cost_overrun'] = model
self.scalers['cost_overrun'] = scaler
self.feature_columns['cost_overrun'] = used_features
metrics = ModelMetrics(
model_name='cost_overrun',
accuracy=1 - (mae / df['overrun_pct'].std()),
mae=mae,
feature_importance=importance,
training_samples=len(X_train),
last_trained=datetime.now()
)
self.metrics['cost_overrun'] = metrics
return metrics
def train_schedule_delay_model(self, historical_data: pd.DataFrame) -> ModelMetrics:
"""Train model to predict schedule delay probability."""
df = historical_data.copy()
# Binary classification: was project delayed?
df['was_delayed'] = (df['actual_duration'] > df['planned_duration']).astype(int)
feature_cols = [col for col in df.columns
if col not in ['actual_duration', 'was_delayed', 'project_id', 'project_name']]
X, y, used_features = self.prepare_features(df[feature_cols + ['was_delayed']], 'was_delayed')
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)
model = GradientBoostingClassifier(n_estimators=100, max_depth=5, random_state=42)
model.fit(X_train_scaled, y_train)
y_pred = model.predict(X_test_scaled)
accuracy = accuracy_score(y_test, y_pred)
importance = dict(zip(used_features, model.feature_importances_))
self.models['schedule_delay'] = model
self.scalers['schedule_delay'] = scaler
self.feature_columns['schedule_delay'] = used_features
metrics = ModelMetrics(
model_name='schedule_delay',
accuracy=accuracy,
mae=0,
feature_importance=importance,
training_samples=len(X_train),
last_trained=datetime.now()
)
self.metrics['schedule_delay'] = metrics
return metrics
def predict_cost_overrun(self, project_data: Dict) -> PredictionResult:
"""Predict cost overrun for a new project."""
if 'cost_overrun' not in self.models:
raise ValueError("Cost overrun model not trained. Call train_cost_overrun_model first.")
model = self.models['cost_overrun']
scaler = self.scalers['cost_overrun']
features = self.feature_columns['cost_overrun']
# Prepare input
input_df = pd.DataFrame([project_data])
# Encode categorical
for col in input_df.select_dtypes(include=['object']).columns:
if col in self.encoders:
input_df[col] = self.encoders[col].transform(input_df[col].astype(str))
# Ensure all features present
for feat in features:
if feat not in input_df.columns:
input_df[feat] = 0
X = input_df[features].fillna(0)
X_scaled = scaler.transform(X)
prediction = model.predict(X_scaled)[0]
# Get feature importance for this prediction
importance = dict(zip(features, model.feature_importances_))
top_features = sorted(importance.items(), key=lambda x: -x[1])[:5]
# Identify risk factors
risk_factors = []
if prediction > 10:
risk_factors.append(f"High overrun risk: {prediction:.1f}%")
for feat, imp in top_features[:3]:
risk_factors.append(f"Key factor: {feat} (importance: {imp:.2%})")
return PredictionResult(
prediction=prediction,
confidence=0.8, # Could calculate from model uncertainty
prediction_type='cost_overrun_percentage',
features_used=features,
feature_importance=dict(top_features),
comparable_projects=[],
risk_factors=risk_factors
)
def predict_delay_probability(self, project_data: Dict) -> PredictionResult:
"""Predict probability of schedule delay."""
if 'schedule_delay' not in self.models:
raise ValueError("Schedule delay model not trained.")
model = self.models['schedule_delay']
scaler = self.scalers['schedule_delay']
features = self.feature_columns['schedule_delay']
input_df = pd.DataFrame([project_data])
for col in input_df.select_dtypes(include=['object']).columns:
if col in self.encoders:
input_df[col] = self.encoders[col].transform(input_df[col].astype(str))
for feat in features:
if feat not in input_df.columns:
input_df[feat] = 0
X = input_df[features].fillna(0)
X_scaled = scaler.transform(X)
probability = model.predict_proba(X_scaled)[0][1]
prediction = model.predict(X_scaled)[0]
importance = dict(zip(features, model.feature_importances_))
top_features = sorted(importance.items(), key=lambda x: -x[1])[:5]
risk_factors = []
if probability > 0.7:
risk_factors.append(f"High delay probability: {probability:.1%}")
elif probability > 0.4:
risk_factors.append(f"Moderate delay probability: {probability:.1%}")
return PredictionResult(
prediction=probability,
confidence=probability if prediction == 1 else 1 - probability,
prediction_type='delay_probability',
features_used=features,
feature_importance=dict(top_features),
comparable_projects=[],
risk_factors=risk_factors
)
def find_similar_projects(self, project_data: Dict, historical_data: pd.DataFrame,
n: int = 5) -> pd.DataFrame:
"""Find similar projects from historical data."""
from sklearn.neighbors import NearestNeighbors
numeric_cols = historical_data.select_dtypes(include=[np.number]).columns.tolist()
exclude = ['final_cost', 'actual_duration', 'overrun_pct']
feature_cols = [c for c in numeric_cols if c not in exclude]
X = historical_data[feature_cols].fillna(0)
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
# Prepare new project
new_project = pd.DataFrame([project_data])[feature_cols].fillna(0)
new_scaled = scaler.transform(new_project)
# Find neighbors
nn = NearestNeighbors(n_neighbors=min(n, len(X)), metric='euclidean')
nn.fit(X_scaled)
distances, indices = nn.kneighbors(new_scaled)
similar = historical_data.iloc[indices[0]].copy()
similar['similarity_score'] = 1 / (1 + distances[0])
return similar
def generate_prediction_report(self, project_data: Dict, historical_data: pd.DataFrame) -> str:
"""Generate comprehensive prediction report."""
lines = ["# Project Prediction Report", ""]
lines.append(f"**Generated:** {datetime.now().strftime('%Y-%m-%d %H:%M')}")
lines.append(f"**Project:** {project_data.get('project_name', 'New Project')}")
lines.append("")
# Cost prediction
if 'cost_overrun' in self.models:
cost_pred = self.predict_cost_overrun(project_data)
lines.append("## Cost Overrun Prediction")
lines.append(f"**Predicted Overrun:** {cost_pred.prediction:.1f}%")
lines.append(f"**Confidence:** {cost_pred.confidence:.1%}")
lines.append("")
lines.append("**Key Factors:**")
for feat, imp in list(cost_pred.feature_importance.items())[:5]:
lines.append(f"- {feat}: {imp:.2%}")
lines.append("")
# Schedule prediction
if 'schedule_delay' in self.models:
delay_pred = self.predict_delay_probability(project_data)
lines.append("## Schedule Delay Prediction")
lines.append(f"**Delay Probability:** {delay_pred.prediction:.1%}")
lines.append("")
# Similar projects
lines.append("## Similar Historical Projects")
similar = self.find_similar_projects(project_data, historical_data, n=5)
for _, row in similar.iterrows():
name = row.get('project_name', 'Project')
overrun = row.get('overrun_pct', 0)
similarity = row.get('similarity_score', 0)
lines.append(f"- **{name}**: {overrun:.1f}% overrun (similarity: {similarity:.1%})")
# Risk summary
lines.append("")
lines.append("## Risk Summary")
all_risks = []
if 'cost_overrun' in self.models:
all_risks.extend(cost_pred.risk_factors)
if 'schedule_delay' in self.models:
all_risks.extend(delay_pred.risk_factors)
for risk in all_risks:
lines.append(f"- ⚠️ {risk}")
return "\n".join(lines)
快速开始
import pandas as pd
# Load historical data
historical = pd.read_excel("historical_projects.xlsx")
# Initialize analytics
analytics = ConstructionPredictiveAnalytics()
# Train models
cost_metrics = analytics.train_cost_overrun_model(historical)
print(f"Cost model MAE: {cost_metrics.mae:.2f}%")
delay_metrics = analytics.train_schedule_delay_model(historical)
print(f"Delay model accuracy: {delay_metrics.accuracy:.1%}")
# Predict for new project
new_project = {
'project_type': 'Office',
'original_estimate': 5000000,
'gross_area': 50000,
'duration_months': 18,
'complexity_score': 7,
'contractor_experience': 15
}
cost_prediction = analytics.predict_cost_overrun(new_project)
print(f"Predicted overrun: {cost_prediction.prediction:.1f}%")
delay_prediction = analytics.predict_delay_probability(new_project)
print(f"Delay probability: {delay_prediction.prediction:.1%}")
# Generate report
report = analytics.generate_prediction_report(new_project, historical)
print(report)
依赖项
pip install pandas numpy scikit-learn
资源
- 建筑业机器学习:预测模型研究
- 特征工程:建筑业专用特征
评论
支持 Markdown