搜索

基于TensorFlow和Python的机器学习(笔记2) - 张德长 -


发布时间: 2022-11-24 17:57:04    浏览次数:8 次

基于TensorFlow和Python的机器学习(笔记2)

 

 

池化(Pooling)是卷积神经网络中的一个重要的概念,它实际上是一种形式的降采样。有多种不同形式的非线性池化函数,而其中“最大池化(Max pooling)”是最为常见的。它是将输入的图像划分为若干个矩形区域,对每个子区域输出最大值。直觉上,这种机制能够有效的原因在于,在发现一个特征之后,它的精确位置远不及它和其他特征的相对位置的关系重要。池化层会不断地减小数据的空间大小,因此参数的数量和计算量也会下降,这在一定程度上也控制了过拟合。通常来说,CNN的卷积层之间都会周期性地插入池化层。

池化层通常会分别作用于每个输入的特征并减小其大小。目前最常用形式的池化层是每隔2个元素从图像划分出的区块,然后对每个区块中的4个数取最大值。这将会减少75%的数据量。

除了最大池化之外,池化层也可以使用其他池化函数,例如“平均池化”甚至“L2-范数池化”等。

池化操作(Pooling)是CNN中非常常见的一种操作,Pooling层是模仿人的视觉系统对数据进行降维,池化操作通常也叫做子采样(Subsampling)或降采样(Downsampling),在构建卷积神经网络时,往往会用在卷积层之后,通过池化来降低卷积层输出的特征维度,有效减少网络参数的同时还可以防止过拟合现象。

最大池化MaxPooling

平均池化AvgPooling=Average Pooling

主要功能有以下几点:

  • 抑制噪声,降低信息冗余
  • 提升模型的尺度不变性、旋转不变形
  • 降低模型计算量
  • 防止过拟合

下图为最大池化过程的示意图:

 

convolution英 [ˌkɒnvəˈluːʃn]  美 [ˌkɑːnvəˈluːʃn]

  1. [数] 卷积;回旋;盘旋;卷绕

手写数字识别项目(实战)

# 导入依赖包

import numpy as np

import tensorflow as tf

import pandas as pd

from keras.utils import np_utils

from keras.datasets import mnist

import matplotlib.pyplot as plt

from keras.layers import Dropout  # 防止过拟合的层

 

np.random.seed(10)

# 下载数据

(train_image, train_label), (test_image, test_label) = mnist.load_data()

# 查看数据信息

print(type(train_image))

print(type(train_label))

# <class 'numpy.ndarray'>

# <class 'numpy.ndarray'>

print('train_image.shape=', train_image.shape)

print('train_label.shape=', train_label.shape)

print('test_image.shape=', test_image.shape)

print('test_label.shape=', test_label.shape)

 

 

# train_image.shape= (60000, 28, 28)

# train_label.shape= (60000,)

# test_image.shape= (10000, 28, 28)

# test_label.shape= (10000,)

 

# 显示单个图片及其标签

def plot_image(image, label):

    fig = plt.gcf()

    fig.set_size_inches(3, 3)

    fig.suptitle(f'label={label}', color='red')

    plt.imshow(image, cmap='binary')

    plt.show()

 

 

# 显示单个图片及其标签

# print(train_image[0])

# plot_image(train_image[0],train_label[0])

 

# 显示系列图片及其标签,和预测值(如有)

def plot_images(images, labels, predics, idx, num=10):

    fig = plt.gcf()  # 构造一个图表

    fig.set_size_inches(12, 14)  # 设置图表尺寸,英寸为单位

    if num > 25:        num = 25  # 最多显示25张子图

    for i in range(num):

        ax = plt.subplot(5, 5, 1 + i)  # 绘制子图,5行5列中的第i+1个

        ax.imshow(images[idx], cmap='binary')  # 显示图片 以二维矩阵的形式传递图片数据 binary表示灰度显示

        title = f'label={labels[idx]}'  # 设置子标题

        color = 'blue'  # 标题颜色 默认blue

        if predics is not None:  # 如有预测信息,则一并显示

            index = np.argmax(predics[idx])  # 最大值索引,即预测值

            val = str(round(max(predics[idx]), 5))  # 概率

            title += f',predict={index}\nmax={val}'  # 标题

            if labels[idx] != index: color = 'red'  # 预测错误,标题红色

        ax.set_title(title, color=color, fontsize=10)  # 设置子标题

        ax.set_xticks([])  # 设置x轴刻度为空,即不显示x轴刻度

        ax.set_yticks([])

        idx += 1  # 下一个

    plt.show()  # 显示整个图表

 

 

# 显示系列图片及其标签

# plot_images(train_image,train_label,None,100,num=25)

 

# 对图片数据集进行预处理

# 三维张量改成二维张量

# 第一维不变,第二维变成原第二维和第三维的乘积

# 数据类型转换为float32

print(train_image.shape)  # (60000, 28, 28)

x_train = train_image.reshape(train_image.shape[0], train_image.shape[1] * train_image.shape[2]).astype('float32')

print(x_train.shape)  # (60000, 784)

print(test_image.shape)  # (10000, 28, 28)

x_test = test_image.reshape(test_image.shape[0], test_image.shape[1] * test_image.shape[2]).astype('float32')

print(x_test.shape)  # (10000, 784)

print(x_train[0])

# 图像数据归一化,将数据值转换为0-1之间的小数

x_train_norm = x_train / 255

x_test_norm = x_test / 255

print(x_train_norm[0])

# 标签数据预处理,转换为独热码onehot

print(train_label[:5])  # [5 0 4 1 9]

y_train_onehot = np_utils.to_categorical(train_label)

y_test_onehot = np_utils.to_categorical(test_label)

print(y_train_onehot[:5])  # [0. 0. 0. 0. 0. 1. 0. 0. 0. 0.]=5

 

# ■■■建立多层感知模型■■■

# Sequential是线型堆叠容器,相当于多层蛋糕,一层叠一层

# Dense表示浓密的稠密的层,意为连接很稠密的意思,也就是全连接层

from keras.models import Sequential  # 模型容器 多层蛋糕

from keras.layers import Dense  # 密集层 全连接层

 

# 建立线型堆叠/多层蛋糕模型

model = Sequential()

# 建立输入层input layer和隐藏层hidden layer

# 隐藏层神经元个数256,输入层神经元个数784

# 数据初始化采用正态分布的随机数

# normal distribution正态分布随机数

# 初始化的参数包括权重参数weight和偏差参数bias

# 指定激活函数为relu热卤

model.add(Dense(units=1000, input_dim=784, kernel_initializer='normal', activation='relu'))

 

#增加DropOut层,避免过拟合

model.add(Dropout(0.5))

 

#增加第二个隐藏层,同时增加DropOut层

model.add(Dense(units=1000, kernel_initializer='normal', activation='relu'))

model.add(Dropout(0.5))

# 建立输出层

# 输出层神经元个数10

# 数据初始化此阿勇正态分布随机数normal

# 初始化的参数包括权重参数weight和偏差参数bias

# 定义激活函数为softmax

model.add(Dense(units=10, kernel_initializer='normal', activation='softmax'))

# 查看模型的【摘要summary】

print(model.summary())

 

# 模型训练,指定训练方式,也就是模型装配compile

# 损失函数指定为【交叉熵】

# 优化器指定为adam,Adam=Adaptive Moment Estimation,自适应矩估计

# 使用Adam优化器可以使模型更快的收敛,并提高准确率

# metrics设置评估模型的方式是准确率accuracy

model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])

# 开始训练

 

# x输入数据,图像的特征值feature

# y数字图像真实值label

# validation_split训练数据与验证数据比例,验证数据占训练集的比例为20%

# 训练集共60000项数据,将采用其中的60000*0.2=12000项作为验证数据

# epochs轮回次数/轮数,执行10个训练周期

# batch_size每一个批次训练数据个数

# verbose=2 表示显示训练过程

# verbose 0 = silent静默, 1 = progress bar进度条, 2 = one line per epoch每次轮回显示一行数据.

# fit=拟合、匹配,overfitting=过拟合 underfittin=欠拟合

train_history = model.fit(x=x_train_norm, y=y_train_onehot, validation_split=0.2, epochs=10, batch_size=200, verbose=2)

# train_history数据类型是keras.callbacks.History object

# 包含如下字段:epoch、history、model、params、validation_data

# epoch是一个训练次数列表,[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

# history是一个字典,包含了训练的历史数据,

# history包括4个键 accuracy,val_accuracy,loss,val_loss

# 分别是训练数据准确率,验证数据准确率,训练数据损失值,验证数据损失值

# 每个键对应的值都是一个列表,列表元素个数等于输出层神经元个数10

# 'val_loss' = {list: 10} [0.22753198444843292, ...]

# history = {dict: 4} {'loss': [0.43830350041389465, ...]

 

# model是模型数据,包括相当多的信息,例如正则化项 activity_regularizer = {NoneType} None

# 参数params = {dict: 3} {'verbose': 2, 'epochs': 10, 'steps': 240}

# validation_data = {NoneType} None

 

 

print('训练历史数据\n', train_history)

 

 

# 训练结果可视化

def show_train_history(train_history):

    fig = plt.gcf()  # 构造一个图表

    fig.set_size_inches(10, 8)  # 设置图表尺寸,英寸为单位

    fig.suptitle('训练数据可视化', color='red')

    ax1 = plt.subplot(1, 2, 1)  # 1行2列的第一个子图表

    # 训练数据-准确度

    ax1.plot(train_history.history['accuracy'], c='red')

    # 验证数据-准确度

    ax1.plot(train_history.history['val_accuracy'], c='blue')

    ax1.set_title('训练历史记录-accuracy')  # 设置子图表1的标题

    ax1.set_xlabel('Epoch')  # x轴标签

    ax1.set_ylabel('Train')  # y轴标签

    # 设置子图表1的图例

    ax1.legend(['accuracy', 'val_accuracy'], loc='upper left')

    ax2 = plt.subplot(1, 2, 2)  # 1行2列的第二个子图表

    # 训练数据-损失值

    ax2.plot(train_history.history['loss'], c='red')

    # 验证数据-损失值

    ax2.plot(train_history.history['val_loss'], c='blue')

    ax2.set_title('训练历史记录-loss')  # 设置子图表2的标题

    ax2.set_xlabel('Epoch')  # x轴标签

    ax2.set_ylabel('Train')  # y轴标签

    # 设置子图表2的图例

    ax2.legend(['loss', 'val_loss'], loc='upper left')

 

    plt.show()  # 绘制图表

 

 

# 训练数据可视化

# accuracy=train accuracy训练准确率

# val_accuracy=validation accuracy验证准确率

# loss=train loss训练损失值记录

# val_loss=validation loss验证损失值记录

show_train_history(train_history)

 

# 用测试数据来评估模型准确率

# x_test_norm测试数据的feature,图片特征值

# y_test_onehot测试数据的label,图片的真值标签

# 返回在测试模式下模型的损失值和度量值(本例度量值是准确度accuracy)。

 

scores = model.evaluate(x_test_norm, y_test_onehot)

print('测试得分为')

print(scores)  # 打印准确率数据

# scores = {list: 2} [0.0704198107123375, 0.9787999987602234]

# 256个参数 损失值为0.0704198107123375 准确率accuracy为0.9787999987602234

#隐藏层参数增加为1000个 [0.05959093198180199, 0.9830999970436096]

#增加DropOut后,[0.05871669948101044, 0.9815999865531921]

# 预测,要用标准化、归一化的数据进行预测,批处理32, verbose=1表示显示进度条

prediction = model.predict(x_test_norm, batch_size=32, verbose=1)

# 预测数据可视化

# 下标从0开始,共显示25项数据

plot_images(test_image, test_label, prediction, idx=0, num=25)

 

# 混淆矩阵confusion matrix 也叫误差矩阵

# 混淆矩阵用来显示哪些数次预测比较准确,哪些数字预测容易出错

import pandas as pd

 

 

# 独热码转换为普通码

def onehot_convert(predict):

    res = []

    for p in predict:

        res.append(np.argmax(p))

    return res

 

 

pre = onehot_convert(prediction)

crosstab = pd.crosstab(test_label, pre, rownames=['label'], colnames=['predict'])

print(crosstab)

 

# 建立dataFrame

df = pd.DataFrame({'label': test_label, 'predict': pre})

# 查看真实值为5,而预测值为3的数据

df2 = df[(df.label == 5) & (df.predict == 3)]

print(df2)  # label  predict 340       5        3

index = 340 #可视化错误项的图片,分析原因

#plot_image(test_image[index], test_label[index])

 

数据集

训练数据

模型

预测数据

预测错误项

预测结果可视化

 

 

模型

添加DropOut层 避免过拟合

 

Model: "sequential"

_________________________________________________________________

 Layer (type)                Output Shape              Param #   

=================================================================

 dense (Dense)               (None, 1000)              785000    

                                                                 

 dropout (Dropout)           (None, 1000)              0         

                                                                 

 dense_1 (Dense)             (None, 10)                10010     

                                                                 

=================================================================

Total params: 795,010

Trainable params: 795,010

Non-trainable params: 0

_________________________________________________________________

增加隐藏层

Model: "sequential"

_________________________________________________________________

 Layer (type)                Output Shape              Param #   

=================================================================

 dense (Dense)               (None, 1000)              785000    

                                                                 

 dropout (Dropout)           (None, 1000)              0         

                                                                 

 dense_1 (Dense)             (None, 1000)              1001000   

                                                                 

 dropout_1 (Dropout)         (None, 1000)              0         

                                                                 

 dense_2 (Dense)             (None, 10)                10010     

                                                                 

=================================================================

Total params: 1,796,010

Trainable params: 1,796,010

Non-trainable params: 0

_________________________________________________________________

 

增加参数导致过拟合

256个参数

1000个参数-过拟合

[0.0704198107123375, 0.9787999987602234]

loss value & metrics values(accuracy)

损失值&度量值(准确率)

[0.05959093198180199, 0.9830999970436096]

loss value & metrics values(accuracy)

损失值&度量值(准确率)

 

优化模型的训练效果对比

参数

训练数据可视化

结果

256个参数

[0.0704198107123375, 0.9787999987602234]

loss value & metrics values(accuracy)

损失值&度量值(准确率)

 

label  predict

340       5        3

1003      5        3

1393      5        3

1670      5        3

2035      5        3

2810      5        3

5937      5        3

5972      5        3

8502      5        3

错误项9个

 

1000个参数

[0.05959093198180199, 0.9830999970436096]

loss value & metrics values(accuracy)

损失值&度量值(准确率)

 

label  predict

340       5        3

1393      5        3

2035      5        3

2597      5        3

2810      5        3

3117      5        3

3902      5        3

4360      5        3

5937      5        3

错误项9个

增加DropOut

[0.05871669948101044, 0.9815999865531921]

 

label  predict

340       5        3

1393      5        3

2035      5        3

5937      5        3

错误项4个

 

1000参数+2个隐藏层+DropOut

[0.06338179856538773, 0.9807000160217285]

 

label  predict

1393      5        3

2291      5        3

2597      5        3

5972      5        3

错误项4个

 

结论:使用多层感知器模型识别MNIST手写数字,尝试将模型加宽(增加神经元个数)、加深(增加隐藏层个数),以提高准确率,并加入DropOut层,以避免过度拟合,准确率接近98%。不过,多层感知器有其极限,如果还要进一步提升准确率,就必须使用卷积神经网络CNN。

油耗预测项目(实战)

import io

import os.path

import matplotlib.pyplot as plt

import keras.utils

import tensorflow as tf

import pandas as pd

#下载汽车油耗数据集--加州大学欧文分校

dataset_path = 'C:\\Users\\Administrator\\.keras\\datasets\\auto-mpg.data'

if not os.path.exists(dataset_path):

    dataset_path = keras.utils.get_file('auto-mpg.data',

                                        'http://archive.ics.uci.edu/ml/machine-learning-databases/auto-mpg/auto-mpg.data')

# 'C:\\Users\\Administrator\\.keras\\datasets\\auto-mpg.data'

 

# 利用 pandas 读取数据集,字段有效能(公里数每加仑),气缸数,排量,马力,重量,加速度,型号年份,产地

column_names = ['MPG', 'Cylinders', 'Displacement', 'Horsepower', 'Weight',

                'Acceleration', 'Model Year', 'Origin']

#读取数据

raw_dataset = pd.read_csv(dataset_path, names=column_names, na_values='?', comment='\t', sep=' ', skipinitialspace=True)

#复制数据

dataset = raw_dataset.copy()

#查看数据

print(dataset.head())

print('空白数据个数=', dataset.isna().sum())

#去除空白数据

dataset = dataset.dropna()

#查看数据

print('空白数据个数=', dataset.isna().sum())

#产地数据转换为3列,相当于onehot表示形式

# 对于产地地段, 1 表示美国, 2 表示欧洲, 3 表示日本。

origin = dataset.pop('Origin')

dataset['USA'] = (origin == 1) * 1.0

dataset['Europe'] = (origin == 2) * 1.0

dataset['Japan'] = (origin == 3) * 1.0

print('tail=\n', dataset.tail())

#划分数据集,其中80%用于训练 20%用于测试

train_dataset = dataset.sample(frac=0.8, random_state=0)

test_dataset = dataset.drop(train_dataset.index)

#弹出MPG列数据

train_label = train_dataset.pop('MPG')

test_label = test_dataset.pop('MPG')

#训练数据状态信息

train_stat = train_dataset.describe()

# train_stat.pop('MPG')

print('train_stat=\n', train_stat)

#转置矩阵

train_stat = train_stat.transpose()

 

#定义数据标准化函数

def norm(x):

    return (x - train_stat['mean']) / train_stat['std']

 

#训练数据标准化

normed_train_data = norm(train_dataset)

#测试数据标准化

normed_test_data = norm(test_dataset)

 

print(normed_train_data.shape, train_label.shape)

print(normed_test_data.shape, test_label.shape)

 

train_db = tf.data.Dataset.from_tensor_slices((normed_train_data.values, train_label.values))

train_db = train_db.shuffle(100).batch(32)

 

import matplotlib

 

print(matplotlib.matplotlib_fname())

 

# # 解决plt中文乱码问题-方法1

# # plt.rcParams["font.sans-serif"]=["SimHei"] #设置字体

# # plt.rcParams["axes.unicode_minus"]=False #该语句解决图像中的“-”负号的乱码问题

#

#

# #创建一个有4个子图表的图表,2行2列

# # 接收数据格式要写成2*2的矩阵形式

# #2 2表示图表行数和列数

# #figsize表示图表尺寸

# #fig用于接收整个图表

# #ax1用于接收第1行第1列的子图表

# #ax2用于接收第1行第2列的子图表

# #ax3用于接收第2行第1列的子图表

# #ax4用于接收第2行第2列的子图表

# fig, [[ax1, ax2], [ax3, ax4]] = plt.subplots(2, 2, figsize=(8, 8))

# #设置图标的居中标题,字号fontsize为20,颜色c为红色

# fig.suptitle('油耗关系曲线',fontsize=20,c='red')

# #绘制第1个子图表

# #scatter表示绘制散点图

# #X数据为dataset中的名称为Cylinders的列数据

# #Y数据为dataset中名称为MPG的列数据

# #c表示散点的颜色为red

# #edgecolors表示散点的边缘颜色

# #s表示散点的大小size

# #linewidth表示边缘的线宽

# ax1.scatter(dataset['Cylinders'], dataset['MPG'], c='red', edgecolors='blue', s=100, linewidth=2)

# #设置子图表1的标题

# ax1.set_title('MPG和气缸数 散点图')

# #设置子图表1的x轴标签/名称

# ax1.set_xlabel('气缸数')

# #设置子图表1的y轴标签/名称

# ax1.set_ylabel('MPG')

# #绘制第2个子图表

# ax2.scatter(dataset['Displacement'], dataset['MPG'], c='y', edgecolors='k', s=50, linewidth=2)

# ax2.set_title('MPG和排量 散点图')

# ax2.set_xlabel('排量')

# ax2.set_ylabel('MPG')

# #绘制第3个子图表

# ax3.scatter(dataset['Horsepower'], dataset['MPG'], c='g', edgecolors='b', s=40, linewidth=2)

# ax3.set_title('MPG和马力 散点图')

# ax3.set_xlabel('马力')

# ax3.set_ylabel('MPG')

# #绘制第4个子图表

# ax4.scatter(dataset['Weight'], dataset['MPG'], c='r', edgecolors='k', s=30, linewidth=2)

# ax4.set_title('MPG和重量 散点图')

# ax4.set_xlabel('重量')

# ax4.set_ylabel('MPG')

# #显示图表

# plt.show()

 

 

 

from keras import layers

from keras import losses

 

# 创建模型,3层的全连接网络

class Network(keras.Model):

    def __init__(self):

        super(Network, self).__init__()

        # 创建3个全连接层

        self.fc1 = keras.layers.Dense(64, activation='relu')

        self.fc2 = keras.layers.Dense(64, activation='relu')

        self.fc3 = keras.layers.Dense(1)

    def call(self, inputs, training=None, mask=None):

        # 依次通过 3 个全连接层

        x=self.fc1(inputs)

        x=self.fc2(x)

        x=self.fc3(x)

 

        return x

#创建网络实例

model=Network()

model.build(input_shape=(4,9))

#查看网络概述信息

model.summary()

#创建优化器,指定超参数 学习率learning rate=0.001

optimizer=tf.keras.optimizers.RMSprop(0.0001)

 

for epoch in range(2000):

    for step,(x,y) in enumerate(train_db):

        with tf.GradientTape() as tape:

            out=model(x)# 通过网络获得输出

            #计算损失函数

            loss=tf.reduce_mean(losses.MSE(y,out))

            mae_loss=tf.reduce_mean(losses.MAE(y,out))

        if step%10==0:

            print(epoch,step,loss)

 

        # 计算梯度,并更新

        grad=tape.gradient(loss,model.trainable_variables)

        optimizer.apply_gradients(zip(grad,model.trainable_variables))

 

 

免责声明 基于TensorFlow和Python的机器学习(笔记2) - 张德长 - ,资源类别:文本, 浏览次数:8 次, 文件大小:-- , 由本站蜘蛛搜索收录2022-11-24 05:57:04。此页面由程序自动采集,只作交流和学习使用,本站不储存任何资源文件,如有侵权内容请联系我们举报删除, 感谢您对本站的支持。 原文链接:https://www.cnblogs.com/zhangdezhang/p/16813583.html