Day24 python study
·
import sklearn.datasets
# 获取 sklearn.datasets 模块下所有的属性名
all_names = dir(sklearn.datasets)
print("【1】自带的小数据集 (load_*) - 适合练手/测试:")
print([name for name in all_names if name.startswith("load_")]) # startswith 方法用于判断字符串是否以指定子字符串开头
print("\n【2】在线下载的大数据集 (fetch_*) - 适合真实项目:")
print([name for name in all_names if name.startswith("fetch_")])
print("\n【3】构造的假数据 (make_*) - 适合做实验/画图:")
print([name for name in all_names if name.startswith("make_")])
from sklearn.datasets import fetch_california_housing
import pandas as pd
import matplotlib.pyplot as plt
# 加载数据
california = fetch_california_housing()
X = california.data
y = california.target
feature_names = california.feature_names
# 创建 DataFrame
df = pd.DataFrame(X, columns=feature_names)
df['MedHouseVal'] = y
print("=== 加州房价数据集基本信息 ===")
print(f"样本数量: {df.shape[0]}")
print(f"特征数量: {df.shape[1] - 1}")
print("\n特征名称:")
for i, feature in enumerate(feature_names, 1):
print(f"{i}. {feature}")
print("\n=== 数据统计摘要 ===")
print(df.describe())

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn.tree import DecisionTreeRegressor
from sklearn.ensemble import RandomForestRegressor, GradientBoostingRegressor
from sklearn.metrics import mean_squared_error, r2_score, mean_absolute_error
# 80% 训练,20% 测试
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
regressors = {
"Linear Regression (线性回归)": LinearRegression(),
"Decision Tree (决策树)": DecisionTreeRegressor(random_state=42),
"Random Forest (随机森林)": RandomForestRegressor(n_estimators=100, random_state=42),
"Gradient Boosting (梯度提升)": GradientBoostingRegressor(n_estimators=100, random_state=42)
}
results = [] # 用于存指标
preds_dict = {} # 用于存预测结果(画图用)
print("\n" + "="*30 + " 开始训练与评估 " + "="*30)
for name, model in regressors.items():
# A. 训练
model.fit(X_train, y_train)
# B. 预测
y_pred = model.predict(X_test)
preds_dict[name] = y_pred # 存下来画图
# C. 计算核心指标
r2 = r2_score(y_test, y_pred)
mse = mean_squared_error(y_test, y_pred)
rmse = np.sqrt(mse)
mae = mean_absolute_error(y_test, y_pred)
# D. 记录结果
results.append({
"模型名称": name,
"R2": r2, # 决定系数
"RMSE": rmse, # 均方根误差
"MAE": mae # 平均绝对误差
})
print(f"模型 {name} 训练完成。R2 = {r2:.4f}")
# ==========================================
# 5. 展示指标对比表
# ==========================================
results_df = pd.DataFrame(results).sort_values(by="R2", ascending=False)
print("\n" + "="*30 + " 最终性能排行榜 " + "="*30)
print(results_df)

# --- 模块一:准备工作 ---
# 1. 区分指标类型
# 对于回归问题,R2是效益型指标(越大越好),RMSE和MAE是成本型指标(越小越好)
benefit_cols = ['R2'] # R²分数越大越好
cost_cols = ['RMSE', 'MAE'] # 误差越小越好
# 2. 复制一份数据用于计算
# 首先,我们需要把"模型名称"设为索引,这样其他列就都是数值了
if '模型名称' in results_df.columns:
data_eval = results_df.set_index('模型名称')
else:
data_eval = results_df.copy()
print("=== 数据预处理 ===")
print("处理前的数据:")
print(results_df)
print(f"\n处理后的数据(模型名称作为索引):")
print(data_eval)
print(f"\n索引:{data_eval.index.tolist()}")
print(f"列名:{data_eval.columns.tolist()}")
# 3. 数据类型转换(确保数值列是浮点数)
# 现在只有数值列,可以安全转换了
data_eval = data_eval.astype(float)
print("\n=== 指标类型定义 ===")
print("步骤 1 完成:指标方向已定义。")
print(f"效益型指标 (+) 越大越好: {benefit_cols}")
print(f"成本型指标 (-) 越小越好: {cost_cols}")
print(f"\n用于MCDA分析的数据矩阵:")
print(data_eval)
print(f"\n数据形状:{data_eval.shape}")
print(f"数据类型:")
print(data_eval.dtypes)

# --- 模块二:数据标准化 ---
# 我们使用最小-最大归一化(Min-Max Normalization)
# 对于效益型指标(越大越好):标准化到 [0, 1],值越大越好
# 对于成本型指标(越小越好):需要先取倒数或负向处理,再标准化
from sklearn.preprocessing import MinMaxScaler
import numpy as np
print("=== 开始数据标准化 ===")
print("原始数据:")
print(data_eval)
# 创建标准化的DataFrame
data_normalized = pd.DataFrame(index=data_eval.index)
# 方法1:分别处理效益型和成本型指标(推荐)
scaler = MinMaxScaler()
# 1. 处理效益型指标(越大越好)
for col in benefit_cols:
if col in data_eval.columns:
# 直接标准化,因为越大越好
values = data_eval[col].values.reshape(-1, 1)
normalized_values = scaler.fit_transform(values)
data_normalized[col] = normalized_values.flatten()
print(f"效益型指标 '{col}' 已标准化:原始范围 [{data_eval[col].min():.4f}, {data_eval[col].max():.4f}] -> 标准化范围 [0, 1]")
# 2. 处理成本型指标(越小越好)
for col in cost_cols:
if col in data_eval.columns:
# 对于成本型指标,有两种常用方法:
# 方法A:先取倒数再标准化(适用于正值)
if (data_eval[col] > 0).all(): # 确保所有值都大于0
# 取倒数,使越小越好变为越大越好
inverse_values = 1 / data_eval[col].values.reshape(-1, 1)
normalized_values = scaler.fit_transform(inverse_values)
data_normalized[col] = normalized_values.flatten()
print(f"成本型指标 '{col}' 已标准化(取倒数法):原始范围 [{data_eval[col].min():.4f}, {data_eval[col].max():.4f}] -> 标准化范围 [0, 1]")
else:
# 方法B:使用负向标准化
# 公式:1 - (x - min)/(max - min) = (max - x)/(max - min)
max_val = data_eval[col].max()
min_val = data_eval[col].min()
normalized_values = (max_val - data_eval[col]) / (max_val - min_val)
data_normalized[col] = normalized_values
print(f"成本型指标 '{col}' 已标准化(负向法):原始范围 [{min_val:.4f}, {max_val:.4f}] -> 标准化范围 [0, 1]")
print("\n标准化后的数据:")
print(data_normalized)
# 检查标准化结果
print("\n标准化后的数值范围:")
for col in data_normalized.columns:
print(f"{col}: [{data_normalized[col].min():.4f}, {data_normalized[col].max():.4f}]")
# 显示每个模型的综合表现(简单平均)
print("\n=== 初步综合得分(简单平均)===")
data_normalized['简单平均分'] = data_normalized.mean(axis=1)
sorted_scores = data_normalized['简单平均分'].sort_values(ascending=False)
print("各模型标准化后各指标得分:")
print(data_normalized)
print("\n模型排名(按简单平均分):")
for rank, (model, score) in enumerate(sorted_scores.items(), 1):
print(f"{rank}. {model}: {score:.4f}")
# 保存标准化结果供后续使用
standardized_results = data_normalized.copy()

# --- 模块三:熵权法计算权重 ---
import numpy as np
print("=== 熵权法计算权重 ===")
print("标准化后的数据:")
print(data_normalized)
# 确保没有零值,避免对数计算错误
# 将0替换为一个很小的正数
data_for_entropy = data_normalized.copy()
epsilon = 1e-10 # 一个很小的正数
data_for_entropy = data_for_entropy.replace(0, epsilon)
print("\n数据处理(避免零值):")
print(data_for_entropy)
# 1. 计算每个指标下各方案的比重(概率)
m, n = data_for_entropy.shape # m个方案(模型),n个指标
print(f"\n数据维度:{m} 个模型,{n} 个指标")
# 计算概率矩阵 P
P = data_for_entropy.values / np.sum(data_for_entropy.values, axis=0)
print("\n概率矩阵 P(每列和为1):")
print(P)
# 2. 计算每个指标的熵值
# 公式:e_j = -k * ∑(p_ij * ln(p_ij)),其中 k = 1/ln(m)
k = 1 / np.log(m) # 调节系数
# 计算熵值
entropy_values = np.zeros(n)
for j in range(n):
# 对每个指标计算熵值
p_col = P[:, j]
# 避免ln(0)的情况,使用np.log函数会自动处理
entropy_values[j] = -k * np.sum(p_col * np.log(p_col))
print(f"\n各指标熵值:")
for i, col in enumerate(data_for_entropy.columns):
print(f"{col}: {entropy_values[i]:.6f}")
# 3. 计算差异系数(信息效用值)
# 公式:d_j = 1 - e_j
d_values = 1 - entropy_values
print(f"\n各指标差异系数(信息效用值):")
for i, col in enumerate(data_for_entropy.columns):
print(f"{col}: {d_values[i]:.6f}")
# 4. 计算权重
# 公式:w_j = d_j / ∑d_j
weights = d_values / np.sum(d_values)
print(f"\n各指标权重(熵权法):")
for i, col in enumerate(data_for_entropy.columns):
print(f"{col}: {weights[i]:.6f} ({(weights[i]*100):.2f}%)")
# 创建权重字典和DataFrame
weight_dict = dict(zip(data_for_entropy.columns, weights))
weights_df = pd.DataFrame({
'指标': list(weight_dict.keys()),
'权重': list(weight_dict.values()),
'权重百分比': [f"{w*100:.2f}%" for w in weight_dict.values()]
})
print("\n权重汇总表:")
print(weights_df)

# --- 模块四:TOPSIS 计算与排序 ---
print("=== TOPSIS 综合评价 ===")
# 1. 构建加权规范化矩阵 V
# 使用标准化后的数据 data_normalized 乘以 熵权法权重
print("\n1. 构建加权规范化矩阵 V = 标准化数据 × 权重")
# 创建权重向量,确保顺序与数据列一致
weight_vector = np.array([weight_dict[col] for col in data_normalized.columns])
print(f"权重向量: {weight_vector}")
# 计算加权规范化矩阵
V = data_normalized.values * weight_vector
V_df = pd.DataFrame(V, index=data_normalized.index, columns=data_normalized.columns)
print("\n加权规范化矩阵 V:")
print(V_df)
# 2. 确定正理想解 (V+) 和负理想解 (V-)
# 由于我们已经将所有指标标准化为效益型(越大越好)
# 所以正理想解取每列的最大值,负理想解取每列的最小值
V_plus = V_df.max()
V_minus = V_df.min()
print(f"\n2. 确定理想解和负理想解:")
for col in V_df.columns:
print(f"{col}: 正理想解(V+)={V_plus[col]:.6f}, 负理想解(V-)={V_minus[col]:.6f}")
# 3. 计算欧氏距离
print("\n3. 计算欧氏距离:")
# D+ : 每个模型与正理想解的距离
D_plus = np.sqrt(((V_df - V_plus) ** 2).sum(axis=1))
# D- : 每个模型与负理想解的距离
D_minus = np.sqrt(((V_df - V_minus) ** 2).sum(axis=1))
print("\n各模型到正理想解的距离 D+:")
for model, distance in D_plus.items():
print(f" {model}: {distance:.6f}")
print("\n各模型到负理想解的距离 D-:")
for model, distance in D_minus.items():
print(f" {model}: {distance:.6f}")
# 4. 计算相对接近度 C_i (TOPSIS得分)
# Score = D- / (D+ + D-)
# 值域 [0, 1],越接近1越好
scores = D_minus / (D_plus + D_minus)
print("\n4. 计算相对接近度(TOPSIS得分):")
for model, score in scores.items():
print(f" {model}: {score:.6f}")
# 5. 整理最终结果
print("\n5. 整理最终排名结果:")
# 创建包含原始数据、标准化数据、TOPSIS得分的综合结果表
final_results = pd.DataFrame({
'模型名称': data_eval.index,
'R2_原始': data_eval['R2'],
'RMSE_原始': data_eval['RMSE'],
'MAE_原始': data_eval['MAE'],
'R2_标准化': data_normalized['R2'],
'RMSE_标准化': data_normalized['RMSE'],
'MAE_标准化': data_normalized['MAE'],
'到正理想解距离(D+)': D_plus.values,
'到负理想解距离(D-)': D_minus.values,
'TOPSIS得分': scores.values
})
# 计算排名(得分越高越好)
final_results['排名'] = final_results['TOPSIS得分'].rank(ascending=False, method='min').astype(int)
# 按排名排序
final_results = final_results.sort_values(by='排名')
print("\n=== TOPSIS综合评价结果 ===")
print(final_results.to_string(index=False))

更多推荐
所有评论(0)