机器学习笔记(神经网络算法)

什么是神经网络算法?

  • 神经网络就像一个黑盒子,我们只需要将数据输入进去,经过黑盒子的内部处理,就可以得到我们想要的结果
  • 神经网络的命名来自于神经元
  • 神经网络图如下
    神经网络图

神经网络算法有什么用?

  • 能够解决分类问题,聚类问题,拟合问题等诸多类型问题,可以说的上是比较万能的一种模型

重要概念

  • 输入层
  • 隐藏层
  • 输出层
  • 多层权值
  • 激活函数
  • ReLU函数
  • 代价函数
  • 正向传播
  • 反向传播

输入层

  • 神经网络的头部,接受数据
  • 和线性回归或者逻辑回归一样,都是一组样本,但是不需要在这个时候将Y值放进去

隐藏层

  • 隐藏层可以有多层,在每一层都会得到一个新的预测值,这个预测值会和上一层到这一层的权值有关
  • 隐藏层的预测值个数不一定和特征个数相等,是可以调节的

输出层

  • 得到最终的预测结果,个数必须要和Y的特征个数相同
  • 通过预测值和真实值的特殊处理,可以得到代价函数

多层权值

  • 神经网络是有多层权值的,权值的层数等于总层数-1,在一个3层的神经网络中,有一个隐藏层,那么权值层数就有2个
  • 每一层权值的个数为下一层节点个数*这一层节点个数,即对于输入层来说 X 1 = [ a , b , c ] X_1 = [a, b, c] X1=[a,b,c],有三个节点,下一层的 X 2 = [ a , b ] X_2 = [a, b] X2=[a,b],有两个节点,那么第一层的权值应当是这种形式 W 1 = [ [ a 1 , b 1 , c 1 ] , [ a 2 , b 2 , c 2 ] ] W_1 = [[a_1, b_1, c_1], [a_2, b_2, c_2]] W1=[[a1,b1,c1],[a2,b2,c2]]

激活函数

  • 如果是解决逻辑回归问题,可以选用sigmod函数, h ( z ) = 1 1 + e ( − z ) h(z) = \frac{1}{1 + e^(-z)} h(z)=1+e(z)1

ReLU函数

  • 在神经网络中,ReLU函数也可以作为激活函数,相比sigmod函数,更加简洁、高效,并且不会出现指数爆炸的问题。ReLU函数形式如下:
    f ( x ) = m a x ( 0 , x ) f(x) = max(0, x) f(x)=max(0,x)

代价函数

  • 如果是解决逻辑回归问题,可以选用交叉熵损失函数逻辑回归

正向传播

  • 神经网络的正向传播过程就是求预测值的过程
  • 对于一个只有一个隐藏层的神经网络,它的一组初始 X 1 = [ 1 , 2 , 3 , 4 ] X_1=[1, 2, 3, 4] X1=[1,2,3,4],对应的权值 W 1 = [ [ 0.2 , 0.3 , 0.1 , 0.4 ] , [ 0.1 , 0.2 , 0.4 , 0.3 ] , [ 0.3 , 0.2 , 0.1 , 0.4 ] , [ 0.4 , 0.1 , 0.2 , 0.3 ] ] W_1=[[0.2, 0.3, 0.1, 0.4], [0.1, 0.2, 0.4, 0.3], [0.3, 0.2, 0.1, 0.4], [0.4, 0.1, 0.2, 0.3]] W1=[[0.2,0.3,0.1,0.4],[0.1,0.2,0.4,0.3],[0.3,0.2,0.1,0.4],[0.4,0.1,0.2,0.3]],那么它的 Z 1 = [ 2.7 , 2.9 , 2.6 , 2.4 ] Z_1=[2.7, 2.9, 2.6, 2.4] Z1=[2.7,2.9,2.6,2.4]
  • 再根据ReLU激活函数,得到 A 1 = [ 2.7 , 2.9 , 2.6 , 2.4 ] A_1 = [2.7 , 2.9, 2.6, 2.4] A1=[2.7,2.9,2.6,2.4]
  • 再将 A 1 A_1 A1的结果当作下一层的输入值,继续重复计算,得到 Z 2 Z_2 Z2
  • 并用sigmod函数,代入 Z 2 Z_2 Z2,得到 A 2 A_2 A2 A 2 A_2 A2应该是一个0~1之间的小数,将0.5作为阈值(根据情况也可能不是0.5),大于0.5的变成1,小于等于0.5的变成0,就能得到预测值了

反向传播(以下计算过程只当作参考,不保证正确)

  • 神经网络的反向传播就是根据预测值的准确性,更新每一层权值的过程
  • 如果输出层的值是 A 2 A_2 A2,那么首先得到 d Z 2 = A 2 − y dZ_2 = A_2 - y dZ2=A2y,再通过 1 m ∗ d Z 2 ∗ A 1 T \frac{1}{m} * dZ_2 * A_1^T m1dZ2A1T就可以得到 d W 2 dW_2 dW2,最后 W 2 = d W 1 ∗ l r W_2 = dW_1 * lr W2=dW1lr
  • d Z 1 dZ_1 dZ1的计算要稍微复杂一点,公式为 ( W 2 ∗ d Z 2 ) ∗ ( 1 − A 1 2 ) (W_2 * dZ_2) * (1 - A_1^2) (W2dZ2)(1A12) d W 1 = 1 m ∗ d Z 1 ∗ X T dW_1 = \frac{1}{m} * dZ_1 * X^T dW1=m1dZ1XT

自定义Python代码实现单隐藏层神经网络(自定义代码存在许多问题,不推荐使用,只当作算法的参考)

import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
import matplotlib.pyplot as plt

# 初始化参数
def initialize_parameters(n_x, n_h, n_y):
    """
    n_x是输入层节点个数,n_h是隐藏层节点个数,n_y是输出层节点个数
    """
    W1 = np.random.randn(n_h, n_x) * 0.01
    b1 = np.zeros((n_h, 1))
    W2 = np.random.randn(n_y, n_h) * 0.01
    b2 = np.zeros((n_y, 1))

    assert(W1.shape == (n_h, n_x))
    assert(b1.shape == (n_h, 1))
    assert(W2.shape == (n_y, n_h))
    assert(b2.shape == (n_y, 1))

    parameters = {
        'W1' : W1,
        'b1' : b1,
        'W2' : W2,
        'b2' : b2
    }

    return parameters

# sigmod激活函数
def sigmod(Z):
    return 1 / (1 + np.exp(-Z))

# ReLU激活函数
def ReLU(Z):
    return np.maximum(0, Z)

# 代价函数
def J(A2, y):
    m = y.shape[1]

    cost = -1 / m * np.sum(y * np.log(A2) + (1 - y) * np.log(1 - A2))
    cost = np.squeeze(cost)

    assert(isinstance(cost, float))

    return cost

# 正向传播,得到预测值
def forward_propagation(X, parameters):
    """
    X是输入值,是众多样本中的一行数据
    parameters是一个字典,里面有各个层的权值
    """
    W1 = parameters['W1']
    b1 = parameters['b1']
    W2 = parameters['W2']
    b2 = parameters['b2']

    # 计算Z1
    Z1 = np.dot(W1, X) + b1
    # 用ReLU计算A1
    A1 = ReLU(Z1)
    # 计算Z2
    Z2 = np.dot(W2, A1) + b2
    # 用sigmod得出A2
    A2 = sigmod(Z2)

    # cache存储一次正向传播得到的Z和A,反向传播更新权值时会用到
    cache = {
        'Z1' : Z1,
        'A1' : A1,
        'Z2' : Z2,
        'A2' : A2
    }
    return cache

# 反向传播,更新权值
def backward_propagation(X, y, parameters, cache, lr):
    m = X.shape[1]

    # 从参数中获取W1和W2,b1和b2
    W1 = parameters['W1']
    b1 = parameters['b1']
    W2 = parameters['W2']
    b2 = parameters['b2']

    # 从cache中获取A1和A2
    A1 = cache['A1']
    A2 = cache['A2']

    # 反向传播得到dW和db
    dZ2 = A2 - y
    dW2 = 1 / m * np.dot(dZ2, A1.T)
    db2 = 1 / m * np.sum(dZ2, axis=1, keepdims=True)
    dZ1 = np.dot(W2.T, dZ2) * (1 - np.power(A1, 2))
    dW1 = 1 / m * np.dot(dZ1, X.T)
    db1 = 1 / m * np.sum(dZ1, axis=1, keepdims=True)

    # 更新参数
    W1 = W1 - lr * dW1
    b1 = b1 - lr * db1
    W2 = W2 - lr * dW2
    b2 = b2 - lr * db2

    # 设置parameters
    parameters = {
        'W1' : W1,
        'b1' : b1,
        'W2' : W2,
        'b2' : b2
    }
    return parameters

# 算法整合
def bp_model(X, y, n_h, lr=0.0002, epochs=10000, err_torlance=1e-12):
    """
    X是所有样本
    y是对应样本输出
    n_h是隐藏层的节点个数
    lr是学习率
    epochs是迭代次数
    """
    np.random.seed(12)
    # 输入层节点个数
    n_x = X.shape[1]
    # 输出层节点个数
    n_y = y.shape[1]

    # 初始化参数
    parameters = initialize_parameters(n_x, n_h, n_y)

    last_cost = 0

    for i in range(epochs):
        # 正向传播,得到预测值
        cache = forward_propagation(X.T, parameters)
        # 计算代价
        cost = J(cache['A2'], y.T)
        # 反向传播,更新权值
        parameters = backward_propagation(X.T, y.T, parameters, cache, lr)
        if i % 100 == 0:
            print("cost:", cost)
        if np.fabs(cost - last_cost) < err_torlance:
            break
        last_cost = cost
    # 返回权值
    return parameters

# 定义绘制决策边界函数
def plot_decision_boundary(model, X, y):
    # 设置最小值、最大值并且给它们一个间隙
    x1_min, x1_max = X[:, 0].min(), X[:, 0].max()
    x2_min, x2_max = X[:, 1].min(), X[:, 1].max()
    h = 0.01
    # 生成一个h距离的网格
    xx, yy = np.meshgrid(np.arange(x1_min, x1_max, h), np.arange(x2_min, x2_max, h))
    # 预测整个网格的函数值,ravel用于转换为一维,且不会产生副本
    Z = model(np.c_[xx.ravel(), yy.ravel()])
    Z = Z.reshape(xx.shape)
    # 画图
    plt.contourf(xx, yy, Z, cmap=plt.cm.Spectral)
    plt.ylabel('x2')
    plt.xlabel('x1')
    plt.scatter(X[:, 0], X[:, 1], c=y)

# 根据得出的parameters对y进行预测
def predict(X, parameters):
    cache = forward_propagation(X, parameters)
    predictions = np.array(cache['A2'] >= 0.5, dtype=int)
    return predictions

if __name__ == '__main__':
    # 读入数据(分类)
    df = pd.read_csv('NeuralNetwork_Data1.csv')
    # 分离X和y
    X = df[['x1', 'x2']].values
    y = df['y'].values.reshape(-1, 1)

    # 切分训练集和测试集
    X_train, x_test, y_train, y_test = train_test_split(X, y, test_size=0.3)

    # 训练模型
    parameters = bp_model(X_train, y_train, n_h=3, lr=0.002, epochs=20000)

    # 绘制决策边界
    plot_decision_boundary(lambda x:predict(x.T, parameters), X_train, y_train)
    plt.title('bp')

    plt.scatter(X_train[:, 0], X_train[:, 1], c=y_train)

使用sklearn的neural_network模块中的MLPClassifier进行分类

# 要添加一个新单元,输入 '# %%'
# 要添加一个新的标记单元,输入 '# %% [markdown]'
# %%
from sklearn.neural_network import MLPClassifier
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
import matplotlib.pyplot as plt


# %%
# 导入数据集
breast_cancer = load_breast_cancer()
# 切分X和y
X = breast_cancer.data
y = breast_cancer.target
# 查看样本数和特征数
print(X.shape)


# %%
# 切分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3)


# %%
# 训练模型
mlp_classifier = MLPClassifier()
mlp_classifier.fit(X_train, y_train)


# %%
# 给出测试数据集预测准确率
print("预测准确率:", mlp_classifier.score(X_test, y_test))


# %%
# 因为数据集的特征数大于3,所以无法将图画出来,这里选择调整隐藏层节点的个数来调整准确率
plt.figure()
# 预测准确率集合
y_predict_list = []
# 隐藏层节点个数集合
hidden_layers = list(range(100, 1000, 100))
for n in hidden_layers:
    mlp_classifier = MLPClassifier((n, ))
    mlp_classifier.fit(X_train, y_train)
    y_predict_list.append(mlp_classifier.score(X_test, y_test))
plt.plot(hidden_layers, y_predict_list)
plt.xticks(hidden_layers)
plt.show()


# %%
  • 得到单隐藏层情况下,节点数由100个到1000个(步长为100)的预测准确率变化
    准确率变化
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值