美文网首页
《机器学习实战:基于Scikit-Learn、Keras和Ten

《机器学习实战:基于Scikit-Learn、Keras和Ten

作者: SeanCheney | 来源:发表于2019-10-17 16:11 被阅读0次

    电脑上看效果好,不用左右滑屏。都调好了,复制粘贴就可以在PyCharm里直接跑起来。

    # -*- coding: utf-8 -*-
    
    # 需要安装和引入的包有tensorflow\pandas\numpy\matplotlib\scikit-learn
    # 使用pip安装:pip install -i https://pypi.tuna.tsinghua.edu.cn/simple/ tensorflow pandas matplotlib scikit-learn
    
    import numpy as np
    import pandas as pd
    import matplotlib.pyplot as plt
    from tensorflow import keras
    
    # 加载Fashion MNIST数据集,格式与MNIST完全相同(70000张灰度图,每张的像素是28 × 28,
    # 共有10类),图的内容是流行物品,每类中的图片更丰富,# 识图的挑战性比MNIST高得多。
    fashion_mnist = keras.datasets.fashion_mnist
    (X_train_full, y_train_full), (X_test, y_test) = fashion_mnist.load_data()
    
    # 训练集的形状和类型
    print('训练集的形状:60000张图片,像素是28×28', X_train_full.shape)
    print('训练集的数据类型', X_train_full.dtype)
    
    # 该数据集已经分成了训练集和测试集,但没有验证集。所以要建一个验证集,另外,因为要用梯度下
    # 降训练神经网络,必须要对输入特征进行缩放。简单起见,通过除以255.0将强度范围变为0-1:
    X_valid, X_train = X_train_full[:5000] / 255.0, X_train_full[5000:] / 255.0
    y_valid, y_train = y_train_full[:5000], y_train_full[5000:]
    
    # Fashion MNIST的分类名列表:
    class_names = ["T-shirt/top", "Trouser", "Pullover", "Dress", "Coat",
                   "Sandal", "Shirt", "Sneaker", "Bag", "Ankle boot"]
    
    # 训练集的第一个y值是4,所以属于Coat
    print('训练集的第一个y值是4,所以属于:', class_names[y_train[0]])
    
    
    # 创建一个Sequential模型,这是Keras最简单的模型,是由单层神经元顺序连起来的,被称为Sequential API
    model = keras.models.Sequential()
    # 接下来创建了第一层,这是一个Flatten层,它的作用是将每个输入图片转变为1D数组:如果输入数据是矩阵X,
    # 该层则计算X.reshape(-1, 1)。该层没有任何参数,只是做一些简单预处理。因为是模型的第一层,必须要指
    # 明input_shape,input_shape不包括批次大小,只是实例的形状。
    model.add(keras.layers.Flatten(input_shape=[28, 28]))
    # 添加一个有300个神经元的紧密层,激活函数是ReLU。每个紧密层只负责自身的权重矩阵,权重矩阵是神经元与输
    # 入的所有连接权重。紧密层还要负责偏置项
    # (每个神经元都有一个偏置项)矢量。
    model.add(keras.layers.Dense(300, activation="relu"))
    # 再添加第二个紧密层,激活函数仍然是ReLU
    model.add(keras.layers.Dense(100, activation="relu"))
    # 最后,加上一个拥有10个神经元的输出层(每有一个类就要有一个神经元),激活函数是softmax(保证输出的
    # 概率和等于1,因为就只有这十个类,具有排他性)
    model.add(keras.layers.Dense(10, activation="softmax"))
    
    # 除了一层一层加层,也可以传递一个层组成的列表:
    # model = keras.models.Sequential([
    #     keras.layers.Flatten(input_shape=[28, 28]),
    #     keras.layers.Dense(300, activation="relu"),
    #     keras.layers.Dense(100, activation="relu"),
    #     keras.layers.Dense(10, activation="softmax")
    # ])
    
    # 模型的summary()方法可以展示所有层,包括每个层的名字(名字是自动生成的,除非建层时指定名字),输出
    # 的形状(None代表批次大小可以是任意值),和参数的数量。
    print(model.summary())
    
    # 获取所有的层
    print(model.layers)
    
    # 每个层的名字
    print([layer.name for layer in model.layers])
    
    # 可以用get_weights()和set_weights()方法,获取神经层的所有参数。对于紧密层,参数包括连接权重和
    # 偏置项:
    hidden1 = model.layers[1]
    weights, biases = hidden1.get_weights()
    print(weights)
    print(weights.shape)
    print(biases)
    print(biases.shape)
    
    
    # 编译模型
    # 首先,因为使用的是稀疏标签(每个实例只有一个目标类的索引,在这个例子中,目标类索引是0到9),且就
    # 是这十个类,没有其它的,所以使用的是"sparse_categorical_crossentropy"损失函数。如果每个实例
    # 的每个类都有一个目标概率(比如独热矢量,[0., 0., 0., 1., 0., 0., 0., 0., 0., 0.],来表示类3),
    # 则就要使用"categorical_crossentropy"损失函数。如果是做二元分类(有一个或多个二元标签),输出层
    # 就得使用"sigmoid"激活函数,损失函数则变为"binary_crossentropy"。对于优化器,"sgd"表示使用随机
    # 梯度下降训练模型。换句话说,Keras会进行反向传播算法。最后,因为是个分类器,最好在训练和评估时测量
    # "accuracy"。
    model.compile(loss="sparse_categorical_crossentropy",
                  optimizer="sgd",
                  metrics=["accuracy"])
    
    # 训练模型
    # 向fit()方法传递了输入特征(X_train)和目标类(y_train),还要要训练的周期数(不设置的话,默认的周期
    # 数是1,肯定是不能收敛到一个好的解的)。另外还传递了验证集(它是可选的)。Keras会在每个周期结束后,
    # 测量损失和指标,这样就可以监测模型的表现。如果模型在训练集上的表现优于在验证集上的表现,可能模型在训
    # 练集上就过拟合了(或者就是存在bug,比如训练集和验证集的数据不匹配)。为节省时间,周期数设成10
    history = model.fit(X_train, y_train, epochs=10, validation_data=(X_valid, y_valid))
    
    
    # 画学习曲线
    # fit()方法会返回History对象,包含:训练参数(history.params)、周期列表(history.epoch)、以及
    # 最重要的包含训练集和验证集的每个周期后的损失和指标的字典(history.history)。如果用这个字典创建一个
    # pandas的DataFrame,然后使用方法plot(),就可以画出学习曲线
    pd.DataFrame(history.history).plot(figsize=(8, 5))
    plt.grid(True)
    plt.gca().set_ylim(0, 1) # 纵坐标的范围设为0-1
    plt.show()
    
    
    # 用测试集评估泛化误差。只需使用evaluate()方法
    print(model.evaluate(X_test, y_test))
    
    
    # 使用模型进行预测
    X_new = X_test[:3]
    y_proba = model.predict(X_new)
    print(y_proba.round(2))
    # 我得到的结果是,输出的是概率值:
    # [[0. 0. 0. 0. 0. 0. 0. 0. 0. 1.]
    #  [0. 0. 1. 0. 0. 0. 0. 0. 0. 0.]
    #  [0. 1. 0. 0. 0. 0. 0. 0. 0. 0.]]
    
    # 输出的是类别名
    y_pred = model.predict_classes(X_new)
    print(np.array(class_names)[y_pred])
    
    
    # 使用Sequential API搭建回归MLP
    from sklearn.datasets import fetch_california_housing
    from sklearn.model_selection import train_test_split
    from sklearn.preprocessing import StandardScaler
    
    # 获取数据
    housing = fetch_california_housing()
    
    # 切分数据集
    X_train_full, X_test, y_train_full, y_test = train_test_split(
        housing.data, housing.target)
    X_train, X_valid, y_train, y_valid = train_test_split(
        X_train_full, y_train_full)
    
    # 做特征缩放
    scaler = StandardScaler()
    X_train = scaler.fit_transform(X_train)
    X_valid = scaler.transform(X_valid)
    X_test = scaler.transform(X_test)
    
    # 使用Sequential API搭建、训练、评估和使用回归MLP做预测,和前面的分类MLP很像。区别在于输出层只有
    # 一个神经元(因为只想预测一个值而已),也没有使用激活函数,损失函数是均方误差。因为数据集有噪音,我
    # 们就是用一个隐藏层,并且神经元也比之前少,以避免过拟合:
    model = keras.models.Sequential([
        keras.layers.Dense(30, activation="relu", input_shape=X_train.shape[1:]),
        keras.layers.Dense(1)
    ])
    # 编译
    model.compile(loss="mean_squared_error", optimizer="sgd")
    # 训练
    history = model.fit(X_train, y_train, epochs=20,
                        validation_data=(X_valid, y_valid))
    # 评估
    mse_test = model.evaluate(X_test, y_test)
    # 预测
    X_new = X_test[:3] # pretend these are new instances
    y_pred = model.predict(X_new)
    print(y_pred)
    
    
    # 保存模型
    # model = keras.layers.Sequential([...]) # or keras.Model([...])
    # model.compile([...])
    # model.fit([...])
    # model.save("my_keras_model.h5")
    
    
    # 加载模型
    # model = keras.models.load_model("my_keras_model.h5")
    
    
    
    # 使用调回创建检查点
    # fit()方法接受参数callbacks,可以让用户指明一个Keras列表,让Keras在训练开始和结束、每个周期开
    # 始和结束、甚至是每个批次的前后调用。例如,ModelCheckpoint可以在每个时间间隔保存检查点,默认是
    # 每个周期结束之后:
    #  [...] # 搭建编译模型
    # checkpoint_cb = keras.callbacks.ModelCheckpoint("my_keras_model.h5")
    # history = model.fit(X_train, y_train, epochs=10, callbacks=[checkpoint_cb])
    
    # 早停的两种方法
    # 另外,如果训练时使用了验证集,可以在创建检查点时设定save_best_only=True,只有当模型在验证集上
    # 取得最优值时才保存模型。这么做可以不必担心训练时间过长和训练集过拟合:只需加载训练好的模型,就能保
    # 证是在验证集上表现最好的模型。
    # checkpoint_cb = keras.callbacks.ModelCheckpoint("my_keras_model.h5",
    #                                                 save_best_only=True)
    # history = model.fit(X_train, y_train, epochs=10,
    #                     validation_data=(X_valid, y_valid),
    #                     callbacks=[checkpoint_cb])
    # model = keras.models.load_model("my_keras_model.h5") # 滚回到最优模型
    
    # 另一种实现早停的方法是使用EarlyStopping调回。当检测到经过几个周期(周期数由参数patience确定),
    # 验证集表现没有提升时,就会中断训练,还能自动滚回到最优模型。可以将保存检查点(避免宕机)和早停
    # (避免浪费时间和资源)结合起来:
    # early_stopping_cb = keras.callbacks.EarlyStopping(patience=10,
    #                                                   restore_best_weights=True)
    # history = model.fit(X_train, y_train, epochs=100,
    #                     validation_data=(X_valid, y_valid),
    #                     callbacks=[checkpoint_cb, early_stopping_cb])
    
    
    

    相关文章

      网友评论

          本文标题:《机器学习实战:基于Scikit-Learn、Keras和Ten

          本文链接:https://www.haomeiwen.com/subject/axhvmctx.html