23、深度学习与强化学习中的模型实现与应用

深度学习与强化学习中的模型实现与应用

在机器学习领域,多种模型和算法在不同的任务中发挥着重要作用。本文将详细介绍Scikit - learn MLP、受限玻尔兹曼机(RBMs)、Keras MLP以及自编码器(Autoencoders)等模型的相关知识和代码示例。

1. Scikit - learn MLP

在使用Scikit - learn的MLPClassifier之前,我们可以先对数据进行可视化,以了解数据的大致情况。以下是绘制前32个样本的代码:

fig = plt.figure(figsize = (8,8))
fig.subplots_adjust(left=0, right=1, bottom=0, top=1, hspace=0.05, 
wspace=0.05)
for i in range(32):
    ax = fig.add_subplot(8, 8, i+1, xticks=[], yticks=[])
    ax.imshow(digits.images[i], cmap=plt.cm.gray_r)
ax.text(0, 1, str(digits.target[i]), bbox=dict(facecolor='white'))

我们共有1797个样本。接下来,了解一下Scikit - learn MLP模型的关键参数:
- hidden_layer_sizes :指定隐藏层的数量和每个隐藏层的神经元数量。例如, hidden_layer_sizes = (5,3,3) 表示有三个隐藏层,第一层有5个神经元,第二层有3个,第三层有3个。默认值是 (100,) ,即一个包含100个神经元的隐藏层。
- activation :隐藏层的激活函数,有四种可用,默认是 relu
- relu :修正线性单元函数, f(x) = max(0, x)
- logistic :逻辑Sigmoid函数, f(x) = 1 / (1 + exp(-x))
- identity :无操作激活,用于实现线性瓶颈, f(x) = x
- tanh :双曲正切函数, f(x) = tanh(x)
- solver :用于权重优化,有三种选项,默认是 adam
- adam :由Diederik Kingma和Jimmy Ba提出的基于随机梯度的优化器,适用于大型数据集。
- lbfgs :属于拟牛顿方法家族,适用于小型数据集。
- sgd :随机梯度下降。
- max_iter :求解器收敛的最大迭代次数,默认是200。
- learning_rate_init :控制权重更新步长的初始学习率(仅适用于 sgd adam 求解器),默认是0.001。

由于MLP对特征缩放敏感,建议在建模前对数据进行缩放或归一化。以下是使用Scikit - learn MLPClassifier的示例代码:

# split data to training and testing data
X_train, X_test, y_train, y_test = train_test_split(digits.data, digits.target, test_size=0.2, random_state=2017)
print ('Number of samples in training set: %d' %(len(y_train)))
print ('Number of samples in test set: %d' %(len(y_test)))

# Standardise data, and fit only to the training data
scaler = StandardScaler()
scaler.fit(X_train)

# Apply the transformations to the data
X_train_scaled = scaler.transform(X_train)
X_test_scaled = scaler.transform(X_test)

# Initialize ANN classifier
mlp = MLPClassifier(hidden_layer_sizes=(100), activation='logistic',  max_iter = 100)

# Train the classifier with the training data
mlp.fit(X_train_scaled,y_train)

print("Training set score: %f" % mlp.score(X_train_scaled, y_train))
print("Test set score: %f" % mlp.score(X_test_scaled, y_test))

# predict results from the test data
X_test_predicted = mlp.predict(X_test_scaled)

fig = plt.figure(figsize=(8, 8))  # figure size in inches
fig.subplots_adjust(left=0, right=1, bottom=0, top=1, hspace=0.05, wspace=0.05)

# plot the digits: each image is 8x8 pixels
for i in range(32):
    ax = fig.add_subplot(8, 8, i + 1, xticks=[], yticks=[])
    ax.imshow(X_test.reshape(-1, 8, 8)[i], cmap=plt.cm.gray_r)
    # label the image with the target value
    if X_test_predicted[i] == y_test[i]:
        ax.text(0, 1, X_test_predicted[i], color='green', bbox=dict(facecolor='white'))
    else:
        ax.text(0, 1, X_test_predicted[i], color='red', bbox=dict(facecolor='white'))

运行上述代码后,训练集得分和测试集得分分别为0.990953和0.983333。

2. 受限玻尔兹曼机(RBMs)

受限玻尔兹曼机(RBM)是由Geoffrey Hinton在2007年提出的,它可以学习样本训练数据输入的概率分布。RBM在监督/无监督机器学习的不同领域有广泛应用,如特征学习、降维、分类、协同过滤和主题建模等。

以电影评分为例,RBM可以根据用户评分发现潜在因素,解释电影选择的激活情况。RBM的能量函数为 E(v, h) = – aTv – bTh – vTWh ,可见输入层的概率函数为:
[f(v) = - \sum_{i} \log \left( \sum_{h} e^{a^T v + h^T b + v^T W h} \right)]

下面我们将构建一个基于BernoulliRBM的手写数字数据集的逻辑回归模型,并与普通逻辑回归模型的准确率进行比较。

# Function to nudge the dataset
def nudge_dataset(X, Y):
    """
    This produces a dataset 5 times bigger than the original one,
    by moving the 8x8 images in X around by 1px to left, right, down, up
    """
    direction_vectors = [
        [[0, 1, 0],
         [0, 0, 0],
         [0, 0, 0]],
        [[0, 0, 0],
         [1, 0, 0],
         [0, 0, 0]],
        [[0, 0, 0],
         [0, 0, 1],
         [0, 0, 0]],
        [[0, 0, 0],
         [0, 0, 0],
         [0, 1, 0]]]
    shift = lambda x, w: convolve(x.reshape((8, 8)), mode='constant',
                                  weights=w).ravel()
    X = np.concatenate([X] +
                       [np.apply_along_axis(shift, 1, X, vector)
                        for vector in direction_vectors])
    Y = np.concatenate([Y for _ in range(5)], axis=0)
    return X, Y

# Example adapted from scikit-learn documentation
import numpy as np
import matplotlib.pyplot as plt
from sklearn import linear_model, datasets, metrics
from sklearn.model_selection import train_test_split, GridSearchCV
from sklearn.neural_network import BernoulliRBM
from sklearn.pipeline import Pipeline
from scipy.ndimage import convolve

# Load Data
digits = datasets.load_digits()
X = np.asarray(digits.data, 'float32')
y = digits.target
X, y = nudge_dataset(X, digits.target)

# Scale the features such that the values are between 0-1 scale
X = (X - np.min(X, 0)) / (np.max(X, 0) + 0.0001)

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, 
random_state=2017)
print (X.shape)
print (y.shape)

# Gridsearch for logistic regression
# perform a grid search on the 'C' parameter of Logistic
params = {"C": [1.0, 10.0, 100.0]}
Grid_Search = GridSearchCV(LogisticRegression(), params, n_jobs = -1, 
verbose = 1)
Grid_Search.fit(X_train, y_train)

# print diagnostic information to the user and grab the
print ("Best Score: %0.3f" % (Grid_Search.best_score_))
# best model
bestParams = Grid_Search.best_estimator_.get_params()
print (bestParams.items())

# evaluate using Logistic Regression and only the raw pixel
logistic = LogisticRegression(C = 100)
logistic.fit(X_train, y_train)
print ("Train accuracy: ", metrics.accuracy_score(y_train, logistic.predict(X_train)))
print ("Test accuracy: ", metrics.accuracy_score(y_test, logistic.predict(X_test)))

运行上述代码,普通逻辑回归模型的训练准确率和测试准确率分别为0.797440178075和0.800779076238。

接下来,我们对RBM + 逻辑回归模型进行网格搜索:

# initialize the RBM + Logistic Regression pipeline
rbm = BernoulliRBM()
logistic = LogisticRegression()
classifier = Pipeline([("rbm", rbm), ("logistic", logistic)])
params = {
    "rbm__learning_rate": [0.1, 0.01, 0.001],
    "rbm__n_iter": [20, 40, 80],
    "rbm__n_components": [50, 100, 200],
    "logistic__C": [1.0, 10.0, 100.0]}

# perform a grid search over the parameter
Grid_Search = GridSearchCV(classifier, params, n_jobs = -1, verbose = 1)
Grid_Search.fit(X_train, y_train)

# print diagnostic information to the user and grab the
# best model
print ("Best Score: %0.3f" % (Grid_Search.best_score_))
print ("RBM + Logistic Regression parameters")
bestParams = Grid_Search.best_estimator_.get_params()
# loop over the parameters and print each of them out
# so they can be manually set
for p in sorted(params.keys()):
    print ("\t %s: %f" % (p, bestParams[p]))

# initialize the RBM + Logistic Regression classifier with
# the cross-validated parameters
rbm = BernoulliRBM(n_components = 200, n_iter = 20, learning_rate = 
0.1,  verbose = False)
logistic = LogisticRegression(C = 100)

# train the classifier and show an evaluation report
classifier = Pipeline([("rbm", rbm), ("logistic", logistic)])
classifier.fit(X_train, y_train)
print (metrics.accuracy_score(y_train, classifier.predict(X_train)))
print (metrics.accuracy_score(y_test, classifier.predict(X_test)))

# plot RBM components
plt.figure(figsize=(15, 15))
for i, comp in enumerate(rbm.components_):
    plt.subplot(20, 20, i + 1)
    plt.imshow(comp.reshape((8, 8)), cmap=plt.cm.gray_r,
               interpolation='nearest')
    plt.xticks(())
    plt.yticks(())
plt.suptitle('200 components extracted by RBM', fontsize=16)
plt.show()

运行结果显示,RBM + 逻辑回归模型的训练准确率和测试准确率分别为0.936839176405和0.932109070673。可以发现,使用RBM的逻辑回归模型比普通逻辑回归模型的得分提高了10%以上。

综上所述,通过对Scikit - learn MLP和RBMs的学习和实践,我们可以看到不同模型在处理数据和提高准确率方面的特点和优势。在实际应用中,我们可以根据数据的特点和任务的需求选择合适的模型。

3. Keras MLP

在Keras中,神经网络被定义为一系列层的序列,这些层的容器是Sequential类。Sequential模型是层的线性堆叠,每一层的输出作为下一层的输入。以下是使用Keras构建MLP的示例代码:

from matplotlib import pyplot as plt
import numpy as np
np.random.seed(2017)
from keras.models import Sequential
from keras.datasets import mnist
from keras.layers import Dense, Activation, Dropout, Input
from keras.models import Model
from keras.utils import np_utils
from IPython.display import SVG
from keras import backend as K
from keras.callbacks import EarlyStopping
from keras.utils.visualize_util import model_to_dot, plot_model

# load data
(X_train, y_train), (X_test, y_test) = mnist.load_data()
input_unit_size = 28*28
X_train = X_train.reshape(X_train.shape[0], input_unit_size)
X_test  = X_test.reshape(X_test.shape[0], input_unit_size)
X_train = X_train.astype('float32')
X_test  = X_test.astype('float32')

# Scale the values by dividing 255 i.e., means foreground (black)
X_train /= 255
X_test  /= 255

# one-hot representation, required for multiclass problems
nb_classes = 10
y_train = np_utils.to_categorical(y_train, nb_classes)
y_test = np_utils.to_categorical(y_test, nb_classes)

print('X_train shape:', X_train.shape)
print(X_train.shape[0], 'train samples')
print(X_test.shape[0], 'test samples')

# create model
model = Sequential()
model.add(Dense(input_unit_size, input_dim=input_unit_size, kernel_initializer='normal', activation='relu'))
model.add(Dense(nb_classes, kernel_initializer='normal', activation='softmax'))

模型编译是一个预计算步骤,它将我们定义的层序列转换为高效的矩阵变换系列。编译模型需要三个参数:优化器、损失函数和评估指标列表。

# Compile model
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
SVG(model_to_dot(model, show_shapes=True).create(prog='dot', format='svg'))

网络使用反向传播算法进行训练,并根据指定的方法和损失函数进行优化。每个epoch可以划分为多个批次。

# model training
model.fit(X_train, y_train, validation_data=(X_test, y_test), nb_epoch=5, batch_size=500, verbose=2)

# Final evaluation of the model
scores = model.evaluate(X_test, y_test, verbose=0)
print("Error: %.2f%%" % (100-scores[1]*100))

运行上述代码后,训练过程中会输出每个epoch的损失和准确率,最终模型的误差率为2.24%。

下面是另一个使用Keras MLP处理糖尿病数据集的示例:

import pandas as pd

# load pima indians dataset
dataset = pd.read_csv('Data/Diabetes.csv')

# split into input (X) and output (y) variables
X = dataset.iloc[:,0:8].values
y = dataset['class'].values     # dependent variables

# create model
model = Sequential()
model.add(Dense(12, input_dim=8, kernel_initializer='uniform', activation='relu'))
model.add(Dense(1, kernel_initializer='uniform', activation='sigmoid'))

# Compile model
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
SVG(model_to_dot(model, show_shapes=True).create(prog='dot', format='svg'))

# Fit the model
model.fit(X, y, epochs=5, batch_size=10)

# evaluate the model
scores = model.evaluate(X, y)
print("%s: %.2f%%" % (model.metrics_names[1], scores[1]*100))

运行该代码后,模型的准确率为68.75%。

4. 自编码器(Autoencoders)

自编码器旨在自动学习训练样本数据的编码表示,无需人工干预。自编码器广泛用于降维和数据去噪。构建自编码器通常包含三个要素:
1. 编码函数 :通过非线性函数将输入映射到隐藏表示,如 z = sigmoid (Wx + b)
2. 解码函数 :将隐藏表示映射回与输入具有相同形状的重构数据,如 x’ = sigmoid(W’y + b’)
3. 损失函数 :用于测量数据的压缩表示和解压缩表示之间的信息损失,例如使用传统的平方误差 ||x - z||² 来测量重构误差。

以下是使用自编码器进行降维的示例代码:

import numpy as np
np.random.seed(2017)
from keras.datasets import mnist
from keras.models import Model
from keras.layers import Input, Dense
from keras.optimizers import Adadelta
from keras.utils import np_utils
from IPython.display import SVG
from keras import backend as K
from keras.callbacks import EarlyStopping
from keras.utils.visualize_util import model_to_dot
from matplotlib import pyplot as plt

# Load mnist data
input_unit_size = 28*28
(X_train, y_train), (X_test, y_test) = mnist.load_data()

# function to plot digits
def draw_digit(data, row, col, n):
    size = int(np.sqrt(data.shape[0]))
    plt.subplot(row, col, n)
    plt.imshow(data.reshape(size, size))
    plt.gray()

# Normalize
X_train = X_train.reshape(X_train.shape[0], input_unit_size)
X_train = X_train.astype('float32')
X_train /= 255
print('X_train shape:', X_train.shape)

# Autoencoder
inputs = Input(shape=(input_unit_size,))
x = Dense(144, activation='relu')(inputs)
outputs = Dense(input_unit_size)(x)
model = Model(input=inputs, output=outputs)
model.compile(loss='mse', optimizer='adadelta')
SVG(model_to_dot(model, show_shapes=True).create(prog='dot', format='svg'))

model.fit(X_train, X_train, nb_epoch=5, batch_size=258)

# plot the images from input layers
show_size = 5
total = 0
plt.figure(figsize=(5,5))
for i in range(show_size):
    for j in range(show_size):
        draw_digit(X_train[total], show_size, show_size, total+1)
        total+=1
plt.show()

# plot the encoded (compressed) layer image
get_layer_output = K.function([model.layers[0].input],
                              [model.layers[1].output])
hidden_outputs = get_layer_output([X_train[0:show_size**2]])[0]
total = 0
plt.figure(figsize=(5,5))
for i in range(show_size):
    for j in range(show_size):
        draw_digit(hidden_outputs[total], show_size, show_size, total+1)
        total+=1
plt.show()

# Plot the decoded (de-compressed) layer images
get_layer_output = K.function([model.layers[0].input],
                              [model.layers[2].output])
last_outputs = get_layer_output([X_train[0:show_size**2]])[0]
total = 0
plt.figure(figsize=(5,5))
for i in range(show_size):
    for j in range(show_size):
        draw_digit(last_outputs[total], show_size, show_size, total+1)
        total+=1
plt.show()

上述代码首先加载MNIST数据集,对数据进行归一化处理,然后构建自编码器模型。模型训练完成后,分别绘制输入层、编码层和解码层的图像。

总结

本文详细介绍了Scikit - learn MLP、受限玻尔兹曼机(RBMs)、Keras MLP以及自编码器(Autoencoders)等模型的相关知识和代码示例。这些模型在处理不同类型的数据和任务时各有优势。例如,Scikit - learn MLP适用于一般的分类任务,RBMs可以发现数据中的潜在因素,Keras MLP提供了丰富的优化器和损失函数选择,自编码器则在降维和数据去噪方面表现出色。在实际应用中,我们可以根据具体的数据特点和任务需求选择合适的模型,并通过调整模型参数来提高模型的性能。

以下是这些模型的对比表格:
| 模型名称 | 适用场景 | 关键参数 | 优势 |
| ---- | ---- | ---- | ---- |
| Scikit - learn MLP | 分类任务 | hidden_layer_sizes、activation、solver等 | 简单易用,对特征缩放敏感 |
| RBMs | 特征学习、降维等 | learning_rate、n_iter、n_components等 | 能发现数据潜在因素 |
| Keras MLP | 多种类型任务 | 优化器、损失函数、评估指标等 | 提供丰富选择,可灵活构建网络 |
| 自编码器 | 降维、数据去噪 | 编码和解码函数参数 | 自动学习数据编码表示 |

下面是使用自编码器进行降维的简单流程图:

graph TD;
    A[加载数据] --> B[数据预处理];
    B --> C[构建自编码器模型];
    C --> D[编译模型];
    D --> E[训练模型];
    E --> F[绘制输入层图像];
    E --> G[绘制编码层图像];
    E --> H[绘制解码层图像];

通过对这些模型的学习和实践,我们可以更好地应对各种机器学习任务,提高数据处理和分析的能力。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值