Python 数据科学与机器学习:从入门到实战

Python 是数据科学和机器学习领域最受欢迎的编程语言。本文将介绍 Python 在数据科学中的应用,包括数据处理、可视化、机器学习算法实现等核心技术。

2025年9月18日
DocsLib Team
Python数据科学机器学习NumPyPandasScikit-learn

Python 数据科学与机器学习:从入门到实战

Python 在数据科学中的优势

Python 已成为数据科学和机器学习领域的首选语言,其优势包括:

核心优势

  1. 丰富的生态系统:NumPy、Pandas、Scikit-learn、TensorFlow 等强大库
  2. 简洁易读:语法简单,代码可读性强
  3. 社区支持:活跃的开源社区和丰富的学习资源
  4. 跨平台兼容:支持 Windows、macOS、Linux
  5. 集成能力强:易于与其他工具和语言集成
  6. 可视化支持:Matplotlib、Seaborn、Plotly 等可视化库

环境搭建

Anaconda 安装

# 下载并安装 Anaconda
# 访问 https://www.anaconda.com/products/distribution

# 验证安装
conda --version
python --version

# 创建虚拟环境
conda create -n data-science python=3.9
conda activate data-science

# 安装核心包
conda install numpy pandas matplotlib seaborn scikit-learn jupyter

核心库安装

# 使用 pip 安装
pip install numpy pandas matplotlib seaborn scikit-learn jupyter
pip install plotly bokeh
pip install tensorflow keras  # 深度学习
pip install xgboost lightgbm  # 梯度提升

Jupyter Notebook 配置

# 启动 Jupyter Notebook
jupyter notebook

# 或使用 JupyterLab
jupyter lab

# 安装扩展
jupyter labextension install @jupyter-widgets/jupyterlab-manager

NumPy:数值计算基础

NumPy 是 Python 科学计算的基础库,提供高性能的多维数组对象。

基本数组操作

import numpy as np

# 创建数组
arr1 = np.array([1, 2, 3, 4, 5])
arr2 = np.array([[1, 2, 3], [4, 5, 6]])

# 数组属性
print(f"形状: {arr2.shape}")  # (2, 3)
print(f"维度: {arr2.ndim}")   # 2
print(f"大小: {arr2.size}")   # 6
print(f"数据类型: {arr2.dtype}")  # int64

# 创建特殊数组
zeros = np.zeros((3, 4))  # 零数组
ones = np.ones((2, 3))    # 全1数组
eye = np.eye(3)           # 单位矩阵
linspace = np.linspace(0, 10, 5)  # 等间距数组
arange = np.arange(0, 10, 2)      # 等差数组

# 随机数组
random_arr = np.random.random((3, 3))  # 0-1随机数
normal_arr = np.random.normal(0, 1, (3, 3))  # 正态分布

数组运算

# 基本运算
a = np.array([1, 2, 3, 4])
b = np.array([5, 6, 7, 8])

# 元素级运算
print(a + b)  # [6 8 10 12]
print(a * b)  # [5 12 21 32]
print(a ** 2) # [1 4 9 16]

# 数学函数
print(np.sqrt(a))     # 平方根
print(np.exp(a))      # 指数函数
print(np.log(a))      # 自然对数
print(np.sin(a))      # 三角函数

# 统计函数
data = np.random.normal(0, 1, 1000)
print(f"均值: {np.mean(data):.3f}")
print(f"标准差: {np.std(data):.3f}")
print(f"最大值: {np.max(data):.3f}")
print(f"最小值: {np.min(data):.3f}")

数组索引和切片

# 二维数组索引
arr = np.array([[1, 2, 3, 4],
                [5, 6, 7, 8],
                [9, 10, 11, 12]])

# 基本索引
print(arr[0, 1])    # 2
print(arr[1:, 2:])  # [[7 8], [11 12]]

# 布尔索引
mask = arr > 6
print(arr[mask])    # [7 8 9 10 11 12]

# 花式索引
indices = [0, 2]
print(arr[indices])  # 选择第0行和第2行

# 条件选择
result = np.where(arr > 6, arr, 0)  # 大于6的保留,否则为0
print(result)

Pandas:数据处理利器

Pandas 提供了强大的数据结构和数据分析工具。

DataFrame 基础操作

import pandas as pd
import numpy as np

# 创建 DataFrame
data = {
    'name': ['Alice', 'Bob', 'Charlie', 'Diana'],
    'age': [25, 30, 35, 28],
    'city': ['New York', 'London', 'Tokyo', 'Paris'],
    'salary': [50000, 60000, 70000, 55000]
}

df = pd.DataFrame(data)
print(df)

# 基本信息
print(f"形状: {df.shape}")  # (4, 4)
print(f"列名: {df.columns.tolist()}")
print(f"数据类型:\n{df.dtypes}")
print(f"基本统计:\n{df.describe()}")

# 查看数据
print(df.head())    # 前5行
print(df.tail())    # 后5行
print(df.info())    # 数据信息

数据选择和过滤

# 列选择
print(df['name'])           # 单列
print(df[['name', 'age']])  # 多列

# 行选择
print(df.iloc[0])           # 按位置
print(df.loc[0])            # 按标签
print(df.iloc[1:3])         # 切片

# 条件过滤
high_salary = df[df['salary'] > 55000]
print(high_salary)

# 多条件过滤
young_high_earners = df[(df['age'] < 30) & (df['salary'] > 50000)]
print(young_high_earners)

# 字符串过滤
ny_people = df[df['city'].str.contains('New')]
print(ny_people)

数据清洗

# 创建包含缺失值的数据
data_with_na = {
    'A': [1, 2, np.nan, 4, 5],
    'B': [np.nan, 2, 3, 4, 5],
    'C': [1, 2, 3, np.nan, 5],
    'D': ['a', 'b', 'c', 'd', 'e']
}

df_na = pd.DataFrame(data_with_na)
print("原始数据:")
print(df_na)

# 检查缺失值
print(f"\n缺失值统计:\n{df_na.isnull().sum()}")
print(f"\n缺失值比例:\n{df_na.isnull().mean()}")

# 处理缺失值
# 删除包含缺失值的行
df_dropped = df_na.dropna()
print(f"\n删除缺失值后: {df_dropped.shape}")

# 填充缺失值
df_filled = df_na.fillna({
    'A': df_na['A'].mean(),  # 用均值填充
    'B': df_na['B'].median(),  # 用中位数填充
    'C': df_na['C'].mode()[0]  # 用众数填充
})
print(f"\n填充后:\n{df_filled}")

# 前向填充和后向填充
df_ffill = df_na.fillna(method='ffill')  # 前向填充
df_bfill = df_na.fillna(method='bfill')  # 后向填充

数据变换

# 数据类型转换
df['age'] = df['age'].astype('float64')
df['city'] = df['city'].astype('category')

# 字符串操作
df['name_upper'] = df['name'].str.upper()
df['name_length'] = df['name'].str.len()

# 数值变换
df['salary_log'] = np.log(df['salary'])
df['salary_scaled'] = (df['salary'] - df['salary'].mean()) / df['salary'].std()

# 分组操作
grouped = df.groupby('city').agg({
    'age': ['mean', 'std'],
    'salary': ['mean', 'max', 'min']
})
print(grouped)

# 透视表
pivot = df.pivot_table(
    values='salary',
    index='city',
    columns='age',
    aggfunc='mean'
)
print(pivot)

数据可视化

Matplotlib 基础

import matplotlib.pyplot as plt
import seaborn as sns

# 设置中文字体和样式
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
sns.set_style("whitegrid")

# 生成示例数据
np.random.seed(42)
x = np.linspace(0, 10, 100)
y1 = np.sin(x) + np.random.normal(0, 0.1, 100)
y2 = np.cos(x) + np.random.normal(0, 0.1, 100)

# 基本线图
plt.figure(figsize=(12, 8))

plt.subplot(2, 2, 1)
plt.plot(x, y1, label='sin(x)', linewidth=2)
plt.plot(x, y2, label='cos(x)', linewidth=2)
plt.title('三角函数图')
plt.xlabel('x')
plt.ylabel('y')
plt.legend()
plt.grid(True)

# 散点图
plt.subplot(2, 2, 2)
plt.scatter(y1, y2, alpha=0.6, c=x, cmap='viridis')
plt.title('散点图')
plt.xlabel('sin(x)')
plt.ylabel('cos(x)')
plt.colorbar(label='x值')

# 直方图
plt.subplot(2, 2, 3)
data = np.random.normal(0, 1, 1000)
plt.hist(data, bins=30, alpha=0.7, color='skyblue', edgecolor='black')
plt.title('正态分布直方图')
plt.xlabel('值')
plt.ylabel('频率')

# 箱线图
plt.subplot(2, 2, 4)
data_groups = [np.random.normal(0, 1, 100),
               np.random.normal(1, 1.5, 100),
               np.random.normal(-1, 0.5, 100)]
plt.boxplot(data_groups, labels=['组1', '组2', '组3'])
plt.title('箱线图')
plt.ylabel('值')

plt.tight_layout()
plt.show()

Seaborn 高级可视化

# 创建示例数据集
np.random.seed(42)
n_samples = 1000

data = pd.DataFrame({
    'x': np.random.normal(0, 1, n_samples),
    'y': np.random.normal(0, 1, n_samples),
    'category': np.random.choice(['A', 'B', 'C'], n_samples),
    'value': np.random.exponential(2, n_samples)
})

# 相关性热力图
plt.figure(figsize=(15, 12))

plt.subplot(2, 3, 1)
corr_matrix = data.select_dtypes(include=[np.number]).corr()
sns.heatmap(corr_matrix, annot=True, cmap='coolwarm', center=0)
plt.title('相关性热力图')

# 分布图
plt.subplot(2, 3, 2)
sns.histplot(data=data, x='value', hue='category', kde=True)
plt.title('分组分布图')

# 小提琴图
plt.subplot(2, 3, 3)
sns.violinplot(data=data, x='category', y='value')
plt.title('小提琴图')

# 散点图矩阵
plt.subplot(2, 3, 4)
sns.scatterplot(data=data, x='x', y='y', hue='category', size='value')
plt.title('分组散点图')

# 回归图
plt.subplot(2, 3, 5)
sns.regplot(data=data, x='x', y='y', scatter_kws={'alpha':0.5})
plt.title('回归图')

# 分面图
plt.subplot(2, 3, 6)
sns.boxplot(data=data, x='category', y='value')
plt.title('分组箱线图')

plt.tight_layout()
plt.show()

机器学习基础

Scikit-learn 入门

from sklearn.datasets import load_iris, load_boston
from sklearn.model_selection import train_test_split, cross_val_score
from sklearn.preprocessing import StandardScaler, LabelEncoder
from sklearn.linear_model import LogisticRegression, LinearRegression
from sklearn.ensemble import RandomForestClassifier, RandomForestRegressor
from sklearn.metrics import accuracy_score, classification_report, mean_squared_error, r2_score
from sklearn.pipeline import Pipeline

# 加载数据集
iris = load_iris()
X_iris, y_iris = iris.data, iris.target

# 数据分割
X_train, X_test, y_train, y_test = train_test_split(
    X_iris, y_iris, test_size=0.2, random_state=42, stratify=y_iris
)

print(f"训练集大小: {X_train.shape}")
print(f"测试集大小: {X_test.shape}")

分类任务

# 创建分类管道
classification_pipeline = Pipeline([
    ('scaler', StandardScaler()),
    ('classifier', LogisticRegression(random_state=42))
])

# 训练模型
classification_pipeline.fit(X_train, y_train)

# 预测
y_pred = classification_pipeline.predict(X_test)
y_pred_proba = classification_pipeline.predict_proba(X_test)

# 评估
accuracy = accuracy_score(y_test, y_pred)
print(f"准确率: {accuracy:.3f}")
print(f"\n分类报告:\n{classification_report(y_test, y_pred, target_names=iris.target_names)}")

# 交叉验证
cv_scores = cross_val_score(classification_pipeline, X_iris, y_iris, cv=5)
print(f"\n交叉验证准确率: {cv_scores.mean():.3f} (+/- {cv_scores.std() * 2:.3f})")

# 随机森林分类器
rf_classifier = RandomForestClassifier(n_estimators=100, random_state=42)
rf_classifier.fit(X_train, y_train)
rf_pred = rf_classifier.predict(X_test)
rf_accuracy = accuracy_score(y_test, rf_pred)
print(f"随机森林准确率: {rf_accuracy:.3f}")

# 特征重要性
feature_importance = pd.DataFrame({
    'feature': iris.feature_names,
    'importance': rf_classifier.feature_importances_
}).sort_values('importance', ascending=False)

print(f"\n特征重要性:\n{feature_importance}")

回归任务

# 创建回归数据
np.random.seed(42)
n_samples = 1000
X_reg = np.random.randn(n_samples, 5)
y_reg = (2 * X_reg[:, 0] + 3 * X_reg[:, 1] - X_reg[:, 2] + 
         0.5 * X_reg[:, 3] + np.random.randn(n_samples) * 0.1)

# 分割数据
X_train_reg, X_test_reg, y_train_reg, y_test_reg = train_test_split(
    X_reg, y_reg, test_size=0.2, random_state=42
)

# 线性回归管道
regression_pipeline = Pipeline([
    ('scaler', StandardScaler()),
    ('regressor', LinearRegression())
])

# 训练和预测
regression_pipeline.fit(X_train_reg, y_train_reg)
y_pred_reg = regression_pipeline.predict(X_test_reg)

# 评估回归模型
mse = mean_squared_error(y_test_reg, y_pred_reg)
r2 = r2_score(y_test_reg, y_pred_reg)
rmse = np.sqrt(mse)

print(f"均方误差 (MSE): {mse:.3f}")
print(f"均方根误差 (RMSE): {rmse:.3f}")
print(f"决定系数 (R²): {r2:.3f}")

# 随机森林回归
rf_regressor = RandomForestRegressor(n_estimators=100, random_state=42)
rf_regressor.fit(X_train_reg, y_train_reg)
rf_pred_reg = rf_regressor.predict(X_test_reg)
rf_r2 = r2_score(y_test_reg, rf_pred_reg)

print(f"随机森林 R²: {rf_r2:.3f}")

模型评估和选择

from sklearn.model_selection import GridSearchCV, RandomizedSearchCV
from sklearn.metrics import confusion_matrix
import seaborn as sns

# 网格搜索优化超参数
param_grid = {
    'classifier__C': [0.1, 1, 10, 100],
    'classifier__penalty': ['l1', 'l2'],
    'classifier__solver': ['liblinear']
}

grid_search = GridSearchCV(
    classification_pipeline,
    param_grid,
    cv=5,
    scoring='accuracy',
    n_jobs=-1
)

grid_search.fit(X_train, y_train)

print(f"最佳参数: {grid_search.best_params_}")
print(f"最佳交叉验证分数: {grid_search.best_score_:.3f}")

# 使用最佳模型预测
best_model = grid_search.best_estimator_
best_pred = best_model.predict(X_test)
best_accuracy = accuracy_score(y_test, best_pred)
print(f"最佳模型测试准确率: {best_accuracy:.3f}")

# 混淆矩阵
cm = confusion_matrix(y_test, best_pred)
plt.figure(figsize=(8, 6))
sns.heatmap(cm, annot=True, fmt='d', cmap='Blues',
            xticklabels=iris.target_names,
            yticklabels=iris.target_names)
plt.title('混淆矩阵')
plt.xlabel('预测标签')
plt.ylabel('真实标签')
plt.show()

高级机器学习技术

集成学习

from sklearn.ensemble import VotingClassifier, BaggingClassifier, AdaBoostClassifier
from sklearn.svm import SVC
from sklearn.naive_bayes import GaussianNB

# 创建基础分类器
classifiers = [
    ('lr', LogisticRegression(random_state=42)),
    ('rf', RandomForestClassifier(n_estimators=100, random_state=42)),
    ('svm', SVC(probability=True, random_state=42)),
    ('nb', GaussianNB())
]

# 投票分类器
voting_clf = VotingClassifier(
    estimators=classifiers,
    voting='soft'  # 使用概率投票
)

voting_clf.fit(X_train, y_train)
voting_pred = voting_clf.predict(X_test)
voting_accuracy = accuracy_score(y_test, voting_pred)
print(f"投票分类器准确率: {voting_accuracy:.3f}")

# Bagging
bagging_clf = BaggingClassifier(
    base_estimator=LogisticRegression(random_state=42),
    n_estimators=100,
    random_state=42
)

bagging_clf.fit(X_train, y_train)
bagging_pred = bagging_clf.predict(X_test)
bagging_accuracy = accuracy_score(y_test, bagging_pred)
print(f"Bagging 准确率: {bagging_accuracy:.3f}")

# AdaBoost
ada_clf = AdaBoostClassifier(
    base_estimator=LogisticRegression(random_state=42),
    n_estimators=100,
    random_state=42
)

ada_clf.fit(X_train, y_train)
ada_pred = ada_clf.predict(X_test)
ada_accuracy = accuracy_score(y_test, ada_pred)
print(f"AdaBoost 准确率: {ada_accuracy:.3f}")

降维技术

from sklearn.decomposition import PCA
from sklearn.manifold import TSNE
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis as LDA

# PCA 降维
pca = PCA(n_components=2)
X_pca = pca.fit_transform(X_iris)

print(f"PCA 解释方差比: {pca.explained_variance_ratio_}")
print(f"累计解释方差: {pca.explained_variance_ratio_.sum():.3f}")

# LDA 降维
lda = LDA(n_components=2)
X_lda = lda.fit_transform(X_iris, y_iris)

# t-SNE 降维
tsne = TSNE(n_components=2, random_state=42)
X_tsne = tsne.fit_transform(X_iris)

# 可视化降维结果
fig, axes = plt.subplots(1, 3, figsize=(15, 5))

# PCA 可视化
scatter = axes[0].scatter(X_pca[:, 0], X_pca[:, 1], c=y_iris, cmap='viridis')
axes[0].set_title('PCA 降维')
axes[0].set_xlabel(f'PC1 ({pca.explained_variance_ratio_[0]:.2%})')
axes[0].set_ylabel(f'PC2 ({pca.explained_variance_ratio_[1]:.2%})')

# LDA 可视化
axes[1].scatter(X_lda[:, 0], X_lda[:, 1], c=y_iris, cmap='viridis')
axes[1].set_title('LDA 降维')
axes[1].set_xlabel('LD1')
axes[1].set_ylabel('LD2')

# t-SNE 可视化
axes[2].scatter(X_tsne[:, 0], X_tsne[:, 1], c=y_iris, cmap='viridis')
axes[2].set_title('t-SNE 降维')
axes[2].set_xlabel('t-SNE 1')
axes[2].set_ylabel('t-SNE 2')

plt.tight_layout()
plt.show()

聚类分析

from sklearn.cluster import KMeans, DBSCAN, AgglomerativeClustering
from sklearn.metrics import silhouette_score, adjusted_rand_score

# K-Means 聚类
kmeans = KMeans(n_clusters=3, random_state=42)
kmeans_labels = kmeans.fit_predict(X_iris)

# DBSCAN 聚类
dbscan = DBSCAN(eps=0.5, min_samples=5)
dbscan_labels = dbscan.fit_predict(X_iris)

# 层次聚类
agg_clustering = AgglomerativeClustering(n_clusters=3)
agg_labels = agg_clustering.fit_predict(X_iris)

# 评估聚类效果
print("聚类评估结果:")
print(f"K-Means 轮廓系数: {silhouette_score(X_iris, kmeans_labels):.3f}")
print(f"DBSCAN 轮廓系数: {silhouette_score(X_iris, dbscan_labels):.3f}")
print(f"层次聚类轮廓系数: {silhouette_score(X_iris, agg_labels):.3f}")

# 与真实标签比较
print(f"\nK-Means ARI: {adjusted_rand_score(y_iris, kmeans_labels):.3f}")
print(f"DBSCAN ARI: {adjusted_rand_score(y_iris, dbscan_labels):.3f}")
print(f"层次聚类 ARI: {adjusted_rand_score(y_iris, agg_labels):.3f}")

# 可视化聚类结果
fig, axes = plt.subplots(2, 2, figsize=(12, 10))

# 真实标签
axes[0, 0].scatter(X_pca[:, 0], X_pca[:, 1], c=y_iris, cmap='viridis')
axes[0, 0].set_title('真实标签')

# K-Means
axes[0, 1].scatter(X_pca[:, 0], X_pca[:, 1], c=kmeans_labels, cmap='viridis')
axes[0, 1].set_title('K-Means 聚类')

# DBSCAN
axes[1, 0].scatter(X_pca[:, 0], X_pca[:, 1], c=dbscan_labels, cmap='viridis')
axes[1, 0].set_title('DBSCAN 聚类')

# 层次聚类
axes[1, 1].scatter(X_pca[:, 0], X_pca[:, 1], c=agg_labels, cmap='viridis')
axes[1, 1].set_title('层次聚类')

plt.tight_layout()
plt.show()

深度学习入门

TensorFlow/Keras 基础

import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers
from sklearn.preprocessing import LabelBinarizer

# 数据预处理
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)

# 标签编码
label_binarizer = LabelBinarizer()
y_train_encoded = label_binarizer.fit_transform(y_train)
y_test_encoded = label_binarizer.transform(y_test)

# 构建神经网络模型
model = keras.Sequential([
    layers.Dense(64, activation='relu', input_shape=(4,)),
    layers.Dropout(0.3),
    layers.Dense(32, activation='relu'),
    layers.Dropout(0.3),
    layers.Dense(3, activation='softmax')
])

# 编译模型
model.compile(
    optimizer='adam',
    loss='categorical_crossentropy',
    metrics=['accuracy']
)

# 训练模型
history = model.fit(
    X_train_scaled, y_train_encoded,
    epochs=100,
    batch_size=16,
    validation_split=0.2,
    verbose=0
)

# 评估模型
test_loss, test_accuracy = model.evaluate(X_test_scaled, y_test_encoded, verbose=0)
print(f"神经网络测试准确率: {test_accuracy:.3f}")

# 可视化训练过程
plt.figure(figsize=(12, 4))

plt.subplot(1, 2, 1)
plt.plot(history.history['loss'], label='训练损失')
plt.plot(history.history['val_loss'], label='验证损失')
plt.title('模型损失')
plt.xlabel('轮次')
plt.ylabel('损失')
plt.legend()

plt.subplot(1, 2, 2)
plt.plot(history.history['accuracy'], label='训练准确率')
plt.plot(history.history['val_accuracy'], label='验证准确率')
plt.title('模型准确率')
plt.xlabel('轮次')
plt.ylabel('准确率')
plt.legend()

plt.tight_layout()
plt.show()

实战项目:房价预测

# 创建房价预测数据集
np.random.seed(42)
n_samples = 1000

# 生成特征
house_data = pd.DataFrame({
    'area': np.random.normal(150, 50, n_samples),  # 面积
    'bedrooms': np.random.poisson(3, n_samples),   # 卧室数
    'bathrooms': np.random.poisson(2, n_samples),  # 浴室数
    'age': np.random.exponential(10, n_samples),   # 房龄
    'location_score': np.random.uniform(1, 10, n_samples),  # 位置评分
    'condition': np.random.choice(['poor', 'fair', 'good', 'excellent'], n_samples)
})

# 生成目标变量(房价)
house_data['price'] = (
    house_data['area'] * 500 +
    house_data['bedrooms'] * 10000 +
    house_data['bathrooms'] * 15000 +
    house_data['location_score'] * 20000 -
    house_data['age'] * 1000 +
    np.random.normal(0, 10000, n_samples)
)

# 处理分类变量
condition_mapping = {'poor': 1, 'fair': 2, 'good': 3, 'excellent': 4}
house_data['condition_encoded'] = house_data['condition'].map(condition_mapping)

print("房价数据集概览:")
print(house_data.head())
print(f"\n数据集形状: {house_data.shape}")
print(f"\n基本统计:\n{house_data.describe()}")

# 特征工程
feature_columns = ['area', 'bedrooms', 'bathrooms', 'age', 'location_score', 'condition_encoded']
X_house = house_data[feature_columns]
y_house = house_data['price']

# 数据分割
X_train_house, X_test_house, y_train_house, y_test_house = train_test_split(
    X_house, y_house, test_size=0.2, random_state=42
)

# 构建预测管道
house_pipeline = Pipeline([
    ('scaler', StandardScaler()),
    ('regressor', RandomForestRegressor(n_estimators=100, random_state=42))
])

# 训练模型
house_pipeline.fit(X_train_house, y_train_house)

# 预测和评估
y_pred_house = house_pipeline.predict(X_test_house)

mse_house = mean_squared_error(y_test_house, y_pred_house)
r2_house = r2_score(y_test_house, y_pred_house)
rmse_house = np.sqrt(mse_house)

print(f"\n房价预测模型评估:")
print(f"均方误差 (MSE): {mse_house:,.0f}")
print(f"均方根误差 (RMSE): {rmse_house:,.0f}")
print(f"决定系数 (R²): {r2_house:.3f}")

# 特征重要性分析
feature_importance_house = pd.DataFrame({
    'feature': feature_columns,
    'importance': house_pipeline.named_steps['regressor'].feature_importances_
}).sort_values('importance', ascending=False)

print(f"\n特征重要性:\n{feature_importance_house}")

# 可视化结果
fig, axes = plt.subplots(2, 2, figsize=(15, 12))

# 预测 vs 实际
axes[0, 0].scatter(y_test_house, y_pred_house, alpha=0.6)
axes[0, 0].plot([y_test_house.min(), y_test_house.max()], 
                [y_test_house.min(), y_test_house.max()], 'r--', lw=2)
axes[0, 0].set_xlabel('实际价格')
axes[0, 0].set_ylabel('预测价格')
axes[0, 0].set_title(f'预测 vs 实际 (R² = {r2_house:.3f})')

# 残差图
residuals = y_test_house - y_pred_house
axes[0, 1].scatter(y_pred_house, residuals, alpha=0.6)
axes[0, 1].axhline(y=0, color='r', linestyle='--')
axes[0, 1].set_xlabel('预测价格')
axes[0, 1].set_ylabel('残差')
axes[0, 1].set_title('残差图')

# 特征重要性
axes[1, 0].barh(feature_importance_house['feature'], feature_importance_house['importance'])
axes[1, 0].set_xlabel('重要性')
axes[1, 0].set_title('特征重要性')

# 价格分布
axes[1, 1].hist(house_data['price'], bins=30, alpha=0.7, edgecolor='black')
axes[1, 1].set_xlabel('房价')
axes[1, 1].set_ylabel('频率')
axes[1, 1].set_title('房价分布')

plt.tight_layout()
plt.show()

最佳实践和技巧

数据科学工作流程

  1. 问题定义:明确业务目标和技术指标
  2. 数据收集:获取相关、高质量的数据
  3. 数据探索:理解数据分布、关系和模式
  4. 数据清洗:处理缺失值、异常值和不一致性
  5. 特征工程:创建、选择和变换特征
  6. 模型选择:选择合适的算法和超参数
  7. 模型评估:使用适当的指标评估性能
  8. 模型部署:将模型投入生产环境
  9. 监控维护:持续监控和更新模型

代码优化技巧

# 使用向量化操作而不是循环
# 慢速方法
result_slow = []
for i in range(len(data)):
    result_slow.append(data[i] ** 2)

# 快速方法
result_fast = np.array(data) ** 2

# 使用 Pandas 的内置方法
# 慢速方法
df_slow = df.copy()
for i in range(len(df_slow)):
    if df_slow.iloc[i]['value'] > 0:
        df_slow.iloc[i, df_slow.columns.get_loc('result')] = 'positive'
    else:
        df_slow.iloc[i, df_slow.columns.get_loc('result')] = 'negative'

# 快速方法
df_fast = df.copy()
df_fast['result'] = np.where(df_fast['value'] > 0, 'positive', 'negative')

# 内存优化
# 使用适当的数据类型
df_optimized = df.copy()
df_optimized['category'] = df_optimized['category'].astype('category')
df_optimized['small_int'] = df_optimized['small_int'].astype('int8')

print(f"原始内存使用: {df.memory_usage(deep=True).sum() / 1024**2:.2f} MB")
print(f"优化后内存使用: {df_optimized.memory_usage(deep=True).sum() / 1024**2:.2f} MB")

模型解释性

# 使用 SHAP 解释模型
try:
    import shap
    
    # 创建解释器
    explainer = shap.TreeExplainer(house_pipeline.named_steps['regressor'])
    
    # 计算 SHAP 值
    X_scaled = house_pipeline.named_steps['scaler'].transform(X_test_house)
    shap_values = explainer.shap_values(X_scaled)
    
    # 可视化
    shap.summary_plot(shap_values, X_test_house, feature_names=feature_columns)
    
except ImportError:
    print("请安装 SHAP: pip install shap")

总结

Python 在数据科学和机器学习领域提供了完整的生态系统:

  1. 数据处理:NumPy 和 Pandas 提供强大的数据操作能力
  2. 可视化:Matplotlib 和 Seaborn 支持丰富的图表类型
  3. 机器学习:Scikit-learn 提供全面的算法库
  4. 深度学习:TensorFlow 和 PyTorch 支持复杂的神经网络
  5. 部署:Flask、FastAPI 等框架支持模型服务化

学习建议

  1. 扎实基础:掌握 Python 语法和核心库
  2. 实践项目:通过实际项目加深理解
  3. 持续学习:关注新技术和最佳实践
  4. 社区参与:参与开源项目和技术讨论
  5. 跨领域知识:了解业务背景和领域知识

数据科学是一个快速发展的领域,保持学习热情和实践精神是成功的关键。通过不断练习和探索,你将能够运用 Python 解决各种复杂的数据问题。

要了解更多信息,请访问 Python 官方文档Scikit-learn 用户指南

返回博客列表
感谢阅读!