Python深度学习算法实战教程零基础入门CNN卷积神经网络图像识别RNN循环神经网络序列预测完整代码示例与常见模型搭建指南
好,咱们今天来聊聊深度学习,尤其是CNN和RNN这两个小家伙。你可能会想:深度学习?那不是专业人士干的吗?其实不然,我现在就带你一步步走进这个神奇的世界,保证你看完就能上手写代码!
为什么说深度学习值得学?
先说个真实故事。我有个朋友,以前是个做财务的,天天对着Excel表格发呆。后来他迷上了机器学习,现在转行做数据分析,年薪翻倍。他说:”其实没那么难,就是多花点时间理解原理,然后动手敲代码。”
深度学习确实看起来高深,但本质很简单——就是让电脑从数据中自己学规律。比如你给电脑看一万张猫的照片,它就能学会区分猫和狗。是不是听起来很酷?
环境准备:别被吓到,很简单
开始之前,你需要准备好Python环境。不用担心,跟着做就行:
# 安装必要的库
# 打开终端或命令行,运行以下命令:
pip install tensorflow pandas numpy matplotlib seaborn
# 或者如果你更倾向PyTorch:
pip install torch torchvision pandas numpy matplotlib
安装完这些,你就有了深度学习的基本工具。我推荐用Jupyter Notebook写代码,因为它可以逐行运行,方便调试,就像做实验一样。
第一部分:认识神经网络
在学CNN和RNN之前,我们先来理解最基础的神经网络——就像人脑的简化版。
import tensorflow as tf
from tensorflow import keras
import numpy as np
# 最简单的神经网络:全连接层
model = keras.Sequential([
keras.layers.Dense(128, activation='relu', input_shape=(784,)),
keras.layers.Dense(64, activation='relu'),
keras.layers.Dense(10, activation='softmax') # 10个类别
])
model.summary() # 看看模型长什么样
输出类似这样:
Model: "sequential"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
dense (Dense) (None, 128) 100352
_________________________________________________________________
dense_1 (Dense) (None, 64) 8256
_________________________________________________________________
dense_2 (Dense) (None, 10) 650
=================================================================
Total params: 109,258
Trainable params: 109,258
Non-trainable params: 0
简单说,数据从这里进去,经过一层层计算,最后输出结果。每一步都在”学习”如何把输入变成正确的输出。
第二部分:CNN卷积神经网络——图像识别的王者
CNN是处理图像的神器。你可能听说过它是做图像分类的,但你知道它为什么厉害吗?
CNN的核心思想:局部感知
想象一下,你以前看照片是从左上角一直看到右下角。但CNN不一样,它先看一小块,再看旁边一小块,然后自己组合出完整的画面。这就像我们看字的时候,不是一眼看整个字,而是先看笔画,再看结构。
动手搭建一个图像分类模型
我们用经典的MNIST数据集——就是那些手写的0-9数字。
# 加载并预处理数据
(x_train, y_train), (x_test, y_test) = keras.datasets.mnist.load_data()
# 归一化:把像素值从0-255变成0-1
x_train = x_train.astype('float32') / 255.0
x_test = x_test.astype('float32') / 255.0
# 调整形状,CNN需要4D输入:(样本数, 高, 宽, 通道)
x_train = x_train.reshape(-1, 28, 28, 1)
x_test = x_test.reshape(-1, 28, 28, 1)
接下来是构建CNN的主体:
cnn_model = keras.Sequential([
# 第一个卷积层:提取低级特征(边缘、线条)
keras.layers.Conv2D(32, (3, 3), activation='relu', input_shape=(28, 28, 1)),
keras.layers.MaxPooling2D((2, 2)),
# 第二个卷积层:提取更复杂的特征
keras.layers.Conv2D(64, (3, 3), activation='relu'),
keras.layers.MaxPooling2D((2, 2)),
# 第三个卷积层:继续提取高级特征
keras.layers.Conv2D(64, (3, 3), activation='relu'),
# 展平,准备进入全连接层
keras.layers.Flatten(),
# 全连接层:做最终分类
keras.layers.Dense(64, activation='relu'),
keras.layers.Dropout(0.5), # 防止过拟合
keras.layers.Dense(10, activation='softmax') # 输出10个类别的概率
])
cnn_model.summary()
现在编译并训练:
cnn_model.compile(
optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy']
)
history = cnn_model.fit(
x_train, y_train,
epochs=5,
batch_size=64,
validation_data=(x_test, y_test)
)
# 看看训练结果
test_loss, test_acc = cnn_model.evaluate(x_test, y_test)
print(f'测试准确率: {test_acc * 100:.2f}%')
通常这样的模型能达到99%左右的准确率。是不是很厉害?一个手写数字识别模型,几千行代码都不到。
进阶:用CNN做更复杂的任务
比如分类猫狗图片,你可以用Transfer Learning(迁移学习):
# 加载预训练的MobileNet模型
base_model = keras.applications.MobileNetV2(
weights='imagenet',
include_top=False,
input_shape=(224, 224, 3)
)
# 冻结预训练层
base_model.trainable = False
# 构建完整模型
model = keras.Sequential([
base_model,
keras.layers.GlobalAveragePooling2D(),
keras.layers.Dense(128, activation='relu'),
keras.layers.Dropout(0.3),
keras.layers.Dense(1, activation='sigmoid') # 二分类:猫或狗
])
model.compile(
optimizer='adam',
loss='binary_crossentropy',
metrics=['accuracy']
)
# 训练
model.fit(train_data, epochs=10)
第三部分:RNN循环神经网络——处理序列数据
CNN擅长处理图像,而RNN擅长处理序列数据——比如文字、时间序列、语音等。
RNN的核心思想:记住过去
想象你在读一篇文章,你不会只看一个词就理解意思,而是会结合前面所有的词。RNN就是这样工作的——它有一个”记忆”,能够记住前面看到的信息。
用RNN做文本分类
我们用IMDB电影评论数据集来做例子,判断评论是正面还是负面:
# 加载数据
(x_train, y_train), (x_test, y_test) = keras.datasets.imdb.load_data(num_words=10000)
# 填充序列,让所有评论长度一致
x_train = keras.preprocessing.sequence.pad_sequences(x_train, maxlen=200)
x_test = keras.preprocessing.sequence.pad_sequences(x_test, maxlen=200)
构建RNN模型:
rnn_model = keras.Sequential([
# 词嵌入层:把单词变成向量
keras.layers.Embedding(10000, 64, input_length=200),
# LSTM层:处理序列
keras.layers.LSTM(64, return_sequences=True),
keras.layers.Dropout(0.3),
keras.layers.LSTM(32),
keras.layers.Dropout(0.3),
# 全连接层
keras.layers.Dense(16, activation='relu'),
keras.layers.Dense(1, activation='sigmoid')
])
rnn_model.compile(
optimizer='adam',
loss='binary_crossentropy',
metrics=['accuracy']
)
rnn_model.summary()
训练模型:
history = rnn_model.fit(
x_train, y_train,
epochs=5,
batch_size=64,
validation_data=(x_test, y_test)
)
test_loss, test_acc = rnn_model.evaluate(x_test, y_test)
print(f'测试准确率: {test_acc * 100:.2f}%')
RNN的变体:LSTM和GRU
你可能注意到了,代码里用的是LSTM。LSTM是RNN的一种改进版本,它解决了传统RNN”记不住太久以前的信息”的问题。
# 对比三种序列模型
# 1. 简单的RNN
simple_rnn = keras.Sequential([
keras.layers.Embedding(10000, 64, input_length=200),
keras.layers.SimpleRNN(64),
keras.layers.Dense(1, activation='sigmoid')
])
# 2. LSTM(推荐)
lstm_model = keras.Sequential([
keras.layers.Embedding(10000, 64, input_length=200),
keras.layers.LSTM(64),
keras.layers.Dense(1, activation='sigmoid')
])
# 3. GRU(LSTM的轻量版)
gru_model = keras.Sequential([
keras.layers.Embedding(10000, 64, input_length=200),
keras.layers.GRU(64),
keras.layers.Dense(1, activation='sigmoid')
])
用RNN做时间序列预测
RNN不仅能处理文本,还能预测未来的数据。比如预测股票价格、天气等:
import numpy as np
# 生成模拟的时间序列数据
np.random.seed(42)
data = np.sin(np.linspace(0, 20*np.pi, 1000)) + np.random.normal(0, 0.1, 1000)
# 准备训练数据
def create_dataset(dataset, look_back=60):
X, Y = [], []
for i in range(len(dataset)-look_back):
X.append(dataset[i:i+look_back])
Y.append(dataset[i+look_back])
return np.array(X), np.array(Y)
X, Y = create_dataset(data, look_back=60)
# 分割训练集和测试集
train_size = int(len(X) * 0.8)
X_train, X_test = X[:train_size], X[train_size:]
Y_train, Y_test = Y[:train_size], Y[train_size:]
# 构建模型
seq_model = keras.Sequential([
keras.layers.LSTM(64, return_sequences=True, input_shape=(60, 1)),
keras.layers.LSTM(32),
keras.layers.Dense(16, activation='relu'),
keras.layers.Dense(1)
])
seq_model.compile(optimizer='adam', loss='mse')
# 训练
seq_model.fit(
X_train, Y_train,
epochs=20,
batch_size=32,
validation_data=(X_test, Y_test)
)
# 预测
predictions = seq_model.predict(X_test)
# 可视化结果
import matplotlib.pyplot as plt
plt.figure(figsize=(12, 4))
plt.plot(Y_test[:100], label='真实值')
plt.plot(predictions[:100].flatten(), label='预测值')
plt.legend()
plt.show()
第四部分:常见模型实战
模型一:用CNN做CIFAR-10图像分类
# 加载CIFAR-10数据集
(x_train, y_train), (x_test, y_test) = keras.datasets.cifar10.load_data()
# 归一化
x_train, x_test = x_train / 255.0, x_test / 255.0
# 构建更深的CNN
deep_cnn = keras.Sequential([
keras.layers.Conv2D(32, (3, 3), activation='relu', input_shape=(32, 32, 3)),
keras.layers.BatchNormalization(),
keras.layers.Conv2D(32, (3, 3), activation='relu'),
keras.layers.BatchNormalization(),
keras.layers.MaxPooling2D((2, 2)),
keras.layers.Dropout(0.25),
keras.layers.Conv2D(64, (3, 3), activation='relu'),
keras.layers.BatchNormalization(),
keras.layers.Conv2D(64, (3, 3), activation='relu'),
keras.layers.BatchNormalization(),
keras.layers.MaxPooling2D((2, 2)),
keras.layers.Dropout(0.25),
keras.layers.Flatten(),
keras.layers.Dense(512, activation='relu'),
keras.layers.BatchNormalization(),
keras.layers.Dropout(0.5),
keras.layers.Dense(10, activation='softmax')
])
deep_cnn.compile(
optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy']
)
# 使用数据增强提高泛化能力
data_augmentation = keras.Sequential([
keras.layers.RandomRotation(0.1),
keras.layers.RandomFlip("horizontal"),
keras.layers.RandomZoom(0.1)
])
# 训练
deep_cnn.fit(
data_augmentation(x_train), y_train,
epochs=20,
batch_size=64,
validation_data=(x_test, y_test)
)
模型二:用LSTM做股票价格预测
# 导入真实股票数据
import yfinance as yf
# 获取苹果公司股票数据
data = yf.download('AAPL', start='2020-01-01', end='2023-01-01')
close_prices = data['Close'].values.reshape(-1, 1)
# 归一化
from sklearn.preprocessing import MinMaxScaler
scaler = MinMaxScaler()
close_prices_scaled = scaler.fit_transform(close_prices)
# 创建数据集
def create_dataset(dataset, look_back=60):
X, Y = [], []
for i in range(len(dataset)-look_back):
X.append(dataset[i:i+look_back])
Y.append(dataset[i+look_back])
return np.array(X), np.array(Y)
X, Y = create_dataset(close_prices_scaled, look_back=60)
# 分割数据
train_size = int(len(X) * 0.8)
X_train, X_test = X[:train_size], X[train_size:]
Y_train, Y_test = Y[:train_size], Y[train_size:]
# 构建模型
stock_model = keras.Sequential([
keras.layers.LSTM(128, return_sequences=True, input_shape=(60, 1)),
keras.layers.Dropout(0.2),
keras.layers.LSTM(64, return_sequences=False),
keras.layers.Dropout(0.2),
keras.layers.Dense(32, activation='relu'),
keras.layers.Dense(1)
])
stock_model.compile(optimizer='adam', loss='mse')
# 训练
stock_model.fit(
X_train, Y_train,
epochs=30,
batch_size=32,
validation_data=(X_test, Y_test)
)
# 预测并反归一化
predictions_scaled = stock_model.predict(X_test)
predictions = scaler.inverse_transform(predictions_scaled)
actual = scaler.inverse_transform(Y_test)
# 评估
from sklearn.metrics import mean_squared_error
mse = mean_squared_error(actual, predictions)
print(f'MSE: {mse:.4f}')
模型三:用双向LSTM做文本情感分析
# 加载数据
(x_train, y_train), (x_test, y_test) = keras.datasets.imdb.load_data(num_words=20000)
x_train = keras.preprocessing.sequence.pad_sequences(x_train, maxlen=200)
x_test = keras.preprocessing.sequence.pad_sequences(x_test, maxlen=200)
# 双向LSTM模型
bi_lstm_model = keras.Sequential([
keras.layers.Embedding(20000, 128, input_length=200),
# 双向LSTM可以捕捉前后文信息
keras.layers.Bidirectional(keras.layers.LSTM(64, return_sequences=True)),
keras.layers.Bidirectional(keras.layers.LSTM(32)),
keras.layers.Dense(64, activation='relu'),
keras.layers.Dropout(0.5),
keras.layers.Dense(1, activation='sigmoid')
])
bi_lstm_model.compile(
optimizer='adam',
loss='binary_crossentropy',
metrics=['accuracy']
)
bi_lstm_model.fit(
x_train, y_train,
epochs=10,
batch_size=64,
validation_data=(x_test, y_test)
)
第五部分:常见问题和解决方案
问题一:过拟合
过拟合就是模型”死记硬背”了训练数据,遇到新数据就傻眼了。
解决方法:
# 1. Dropout
keras.layers.Dropout(0.3)
# 2. 数据增强
data_augmentation = keras.Sequential([
keras.layers.RandomRotation(0.2),
keras.layers.RandomFlip("horizontal"),
keras.layers.RandomZoom(0.1)
])
# 3. 减少模型复杂度
# 减少层数或神经元数量
问题二:梯度消失/爆炸
尤其是在RNN中常见。解决方法:
# 使用LSTM或GRU(已经内置了解决方案)
keras.layers.LSTM(64, return_sequences=True)
# 使用梯度裁剪
optimizer = keras.optimizers.Adam(clipnorm=1.0)
问题三:训练太慢
解决方法:
# 使用预训练模型
base_model = keras.applications.MobileNetV2(weights='imagenet', include_top=False)
# 调整学习率
optimizer = keras.optimizers.Adam(learning_rate=0.001)
# 使用GPU加速
# 在Google Colab或本地配置CUDA
第六部分:实战建议
从小项目开始:不要一开始就挑战复杂的任务。先用MNIST(手写数字)练手,再挑战CIFAR-10(彩色图像),最后尝试自己的数据集。
理解原理比调参重要:很多初学者沉迷于调参,但如果不理解原理,调参也是盲目的。建议先搞懂CNN的卷积、池化是什么,RNN的”记忆”是怎么工作的。
多动手,多调试:深度学习是个实践性很强的领域。遇到报错不要慌,打印出数据形状,看看每一步的输出是否符合预期。
利用现成资源:TensorFlow和PyTorch都有很多预训练模型可以直接用。比如你要做图像分类,直接用ResNet、MobileNet等,不用从头训练。
保持耐心:模型训练可能会失败很多次,这是正常的。记录每次实验的参数和结果,从中学习。
总结一下
今天我们一起走过了CNN和RNN的基本原理和实战代码。从最简单的全连接网络,到图像识别的CNN,再到处理序列数据的RNN/LSTM,你应该对深度学习有了直观的认识。
记住几个关键点:
- CNN擅长处理图像,核心是卷积和池化
- RNN/LSTM擅长处理序列数据,核心是有”记忆”
- 调参很重要,但理解原理更重要
- 多动手实践,遇到问题多查文档
深度学习的世界很大,这只是个开始。希望你从今天开始,能做出自己的第一个深度学习项目。有问题随时可以问,我们一起学习进步!
