Python 数据科学与机器学习:从入门到实战
Python 是数据科学和机器学习领域最受欢迎的编程语言。本文将介绍 Python 在数据科学中的应用,包括数据处理、可视化、机器学习算法实现等核心技术。
2025年9月18日
DocsLib Team
Python数据科学机器学习NumPyPandasScikit-learn
Python 数据科学与机器学习:从入门到实战
Python 在数据科学中的优势
Python 已成为数据科学和机器学习领域的首选语言,其优势包括:
核心优势
- 丰富的生态系统:NumPy、Pandas、Scikit-learn、TensorFlow 等强大库
- 简洁易读:语法简单,代码可读性强
- 社区支持:活跃的开源社区和丰富的学习资源
- 跨平台兼容:支持 Windows、macOS、Linux
- 集成能力强:易于与其他工具和语言集成
- 可视化支持: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()
最佳实践和技巧
数据科学工作流程
- 问题定义:明确业务目标和技术指标
- 数据收集:获取相关、高质量的数据
- 数据探索:理解数据分布、关系和模式
- 数据清洗:处理缺失值、异常值和不一致性
- 特征工程:创建、选择和变换特征
- 模型选择:选择合适的算法和超参数
- 模型评估:使用适当的指标评估性能
- 模型部署:将模型投入生产环境
- 监控维护:持续监控和更新模型
代码优化技巧
# 使用向量化操作而不是循环
# 慢速方法
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 在数据科学和机器学习领域提供了完整的生态系统:
- 数据处理:NumPy 和 Pandas 提供强大的数据操作能力
- 可视化:Matplotlib 和 Seaborn 支持丰富的图表类型
- 机器学习:Scikit-learn 提供全面的算法库
- 深度学习:TensorFlow 和 PyTorch 支持复杂的神经网络
- 部署:Flask、FastAPI 等框架支持模型服务化
学习建议
- 扎实基础:掌握 Python 语法和核心库
- 实践项目:通过实际项目加深理解
- 持续学习:关注新技术和最佳实践
- 社区参与:参与开源项目和技术讨论
- 跨领域知识:了解业务背景和领域知识
数据科学是一个快速发展的领域,保持学习热情和实践精神是成功的关键。通过不断练习和探索,你将能够运用 Python 解决各种复杂的数据问题。
要了解更多信息,请访问 Python 官方文档 和 Scikit-learn 用户指南。