机器学习(3)——利用Sklearn和神经网络实现分类

在这里插入图片描述
当散点能找到一条很明显的决策边界的时候,用逻辑回归也可解决问题,当离散点之间难以找到一条明显的决策边界的时候,显然逻辑回归就不再适用了,可以考虑使用神经网络进行回归。
我们不再人工生成数据点,而是通过导入数据集sklearn导入不规则的数据,下面直接贴代码吧~
1.导入必要的库

#数据点杂乱的数据集用回归模型难以找到一条明显的决策边界,考虑用神经网络分类
from sklearn import datasets  #导入数据集sklearn,不再人工生成数据点
import numpy as np
import matplotlib.pyplot as plt

2.生成数据点

#x,y = datasets.make_circles(100)  #生成数据点
#x,y = datasets.make_circles(100,noise=0.1,factor=0.2)  #noise添加噪声,factor为远近程度
x,y = datasets.make_circles(300,noise=0.2,factor=0.3)
plt.scatter(x[:,0],x[:,1],c=y)
plt.show()

没有添加噪声的数据点,也就是这句代码
(x,y = datasets.make_circles(100) #生成数据点)(代码1)
生成的图片是这样的
(图1)
在这里插入图片描述
鉴于这种数据点过于难找决策边界,我们通过添加噪声noise和设置factor来进一步打乱数据点 ,也就是这句代码
x,y = datasets.make_circles(100,noise=0.1,factor=0.2)(代码2)
生成的数据点如下
(图2)
在这里插入图片描述
这里说一下factor,如果单纯的加入噪声生成的数据点是这样的
x,y = datasets.make_circles(300,noise=0.2)(代码3)
(图3)
在这里插入图片描述
可以看到点与点之间很密集,还是很难进行分类的,所以通过加入factor来增大点与点之间的距离(毕竟我们现在只是想实现一个简单的基于sklearn的分类,一切从简就好)
x,y = datasets.make_circles(300,noise=0.2,factor=0.3)(代码4)
(图4)
在这里插入图片描述
这样我们的数据点就生成完毕。

3.确定神经网络的结构
我们生成的是两类数据点的300个样本,所以对应的input layer有300个样本做输入,output layer有两个神经元做输出分别对应两个类别,这里只采用一层hidden layer,我们设了10个神经元。

nn_input_dim = 2
nn_output_dim = 2
num_examples = len(x)

下面是网络正向传播的计算过程
简言之就是input layer经过第一层和第二层间的权重w1,b1得到计算结果z1,hidden layer用这个计算结果z1做输入,通过第二层到输出层的权重w2,b2得到输出结果z2,计算过程中用到激活函数tanh,因为不做激活函数的话即便是经过了10层线性映射最后的结果仍然是线性的,这样层数就没有意义了:

#线性推理,正向梳理过程,也就是输入到输出的过程
w1= np.random.randn(nn_output_dim,10) #input layer到hidden layer之间的权重w1,其中hidden我们设10个神经元
w2 = np.random.randn(10,nn_output_dim) #hiddenlayer到output layer之间的权w2,其中hidden是10个神经元,输出是2分类所以输出dim是2
b1 = np.random.randn(1,10)
b2 = np.random.randn(1,2)
def inference(x1,x2):
    #input layer:
    #X1是第一个特征
    X = np.hstack(([x1],[x2]))  #input层
    #X.shape(2,)
    #w1.shape(2,hidden_dim)  w2.shape(hidden_dim,2)
    #b1.shape(1,hidden_dim)  b2.shaoe(1,2)
    #hidden layer:
    z1 = X.dot(w1) + b1
    a1 = np.tanh(z1)
    z2 = a1.dot(w2) + b2
    exp_z2 = np.exp(z2)
    probs = exp_z2/np.sum(exp_z2,axis=1,keepdims=True)
    print(probs.shape)
    return probs
#print(inference(2,1))
print(inference(2,1))

打印一个结果如下
在这里插入图片描述
4.计算梯度
把上一步的初始化参数部分注释掉,在这个函数里重新定义一下参数,为了方便使用把他们放在一个字典里

#梯度计算
def build_model(hidden_dim,iterations=1000):
    w1 = np.random.randn(nn_input_dim,hidden_dim)
    b1 = np.random.randn(1,hidden_dim)
    w2 = np.random.randn(hidden_dim,nn_output_dim)
    b2 = np.random.randn(1,nn_output_dim)
    model ={'w1':w1,'b1':b1,'w2':w2,'b2':b2}  #定义一个字典把参数放进去

由于我们把上一步前向计算部分的参数注释掉了,在这一步梯度计算的函数里重新定义了参数,所以需要回过头去在前向计算部分重新引用这一部分定义的权重,方法是给def函数加一个参数model,并且在def函数里引用参数
第三步的代码部分修改如下:

def inference(x1,x2,model):#比上一步的def函数括弧内多了一个model
      w1,b1,w2,b2 = model['w1'],model['b1'],model['w2'],model['b2']#函数部分添加此行,其余部分跟上一步写的一样

继续回到梯度下降部分,在def前设置一下学习率

learning_rate = 1e-2

整个模块的代码如下

learning_rate = 1e-2
#梯度计算
def build_model(hidden_dim,iterations=1000):
    w1 = np.random.randn(nn_input_dim,hidden_dim)
    b1 = np.random.randn(1,hidden_dim)
    w2 = np.random.randn(hidden_dim,nn_output_dim)
    b2 = np.random.randn(1,nn_output_dim)
    model ={'w1':w1,'b1':b1,'w2':w2,'b2':b2}

    #梯度下降
    for i in range(iterations):
        #forward
        z1 = x.dot(w1) + b1
        a1 = np.tanh(z1)
        z2 = a1.dot(w2) + b2
        exp_z2 = np.exp(z2)
        probs = exp_z2 / np.sum(exp_z2, axis=1, keepdims=True)
        #backward
        delta3 = probs
        delta3[range(num_examples),y] -= 1 #跳了三步,从交叉熵跳到了softmax之前
        dw2 = a1.T.dot(delta3)  #w2的导数
        db2 = np.sum(delta3,axis=0,keepdims=True)  #b2的导数
        delta2 = delta3.dot(w2.T)*(1-np.power(a1,2))  #tanh求导
        dw1 = np.dot(x.T,delta2)     #w1的导数
        db1 = np.sum(delta2,axis=0)   #b1的导数

        w1 -= learning_rate*dw1
        b1 -= learning_rate * db1
        w2 -= learning_rate * dw2
        b1 -= learning_rate * db1

        model = {'w1': w1, 'b1': b1, 'w2': w2, 'b2': b2}  #输出模型的参数观察一下
        print(model)
    return  model
build_model(hidden_dim=10)

在这里插入图片描述
5.损失函数表示

#输出w,b都是数字难以观察,用损失函数表示出来
def calculate_loss(model):
    w1, b1, w2, b2 = model['w1'], model['b1'], model['w2'], model['b2']
    z1 = x.dot(w1) + b1
    a1 = np.tanh(z1)
    z2 = a1.dot(w2) + b2
    exp_z2 = np.exp(z2)
    probs = exp_z2 / np.sum(exp_z2, axis=1, keepdims=True)
    log_probs = -np.log(probs[range(num_examples),y])
    loss = np.sum(log_probs)
    return loss/num_examples

这部分代码写带第四步代码的上面,然后再修改第四步代码最后print部分的代码为:


        model = {'w1': w1, 'b1': b1, 'w2': w2, 'b2': b2}
        # print(model)
        print(calculate_loss(model))
    return  model

修改完后再运行部分输出结果如下所示:在这里插入图片描述

在这里插入图片描述
完整部分代码:

#数据点杂乱的数据集,用神经网络分类
from sklearn import datasets  #导入数据集sklearn
import numpy as np
import matplotlib.pyplot as plt

x,y = datasets.make_circles(300,noise=0.2,factor=0.3)  #生成数据点,factor为远近程度
plt.scatter(x[:,0],x[:,1],c=y)
plt.show()
learning_rate = 1e-2

nn_input_dim = 2
nn_output_dim = 2
num_examples = len(x)

#线性推理,正向梳理过程,也就是输入到输出的过程
# w1= np.random.randn(nn_output_dim,10) #input layer到hidden layer之间的权重w1,其中hidden我们设10个神经元
# w2 = np.random.randn(10,nn_output_dim) #hiddenlayer到output layer之间的权w2,其中hidden是10个神经元,输出是2分类所以输出dim是2
# b1 = np.random.randn(1,10)
# b2 = np.random.randn(1,2)
def inference(x1,x2,model):
    #input layer:
    #X1是第一个特征
    X = np.hstack(([x1],[x2]))  #input层
    w1,b1,w2,b2 = model['w1'],model['b1'],model['w2'],model['b2']
    #X.shape(2,)
    #w1.shape(2,hidden_dim)  w2.shape(hidden_dim,2)
    #b1.shape(1,hidden_dim)  b2.shaoe(1,2)
    #hidden layer:
    z1 = X.dot(w1) + b1
    a1 = np.tanh(z1)
    z2 = a1.dot(w2) + b2
    exp_z2 = np.exp(z2)
    probs = exp_z2/np.sum(exp_z2,axis=1,keepdims=True)
    print(probs.shape)
    return probs
# print(inference(2,1))


#输出w,b都是数字难以观察,用损失函数表示出来
def calculate_loss(model):
    w1, b1, w2, b2 = model['w1'], model['b1'], model['w2'], model['b2']
    z1 = x.dot(w1) + b1
    a1 = np.tanh(z1)
    z2 = a1.dot(w2) + b2
    exp_z2 = np.exp(z2)
    probs = exp_z2 / np.sum(exp_z2, axis=1, keepdims=True)
    log_probs = -np.log(probs[range(num_examples),y])
    loss = np.sum(log_probs)
    return loss/num_examples


learning_rate = 1e-2
#梯度计算
def build_model(hidden_dim,iterations=1000):
    w1 = np.random.randn(nn_input_dim,hidden_dim)
    b1 = np.random.randn(1,hidden_dim)
    w2 = np.random.randn(hidden_dim,nn_output_dim)
    b2 = np.random.randn(1,nn_output_dim)
    model ={'w1':w1,'b1':b1,'w2':w2,'b2':b2}

    #梯度下降
    for i in range(iterations):
        #forward
        z1 = x.dot(w1) + b1
        a1 = np.tanh(z1)
        z2 = a1.dot(w2) + b2
        exp_z2 = np.exp(z2)
        probs = exp_z2 / np.sum(exp_z2, axis=1, keepdims=True)
        #backward
        delta3 = probs
        delta3[range(num_examples),y] -= 1 #跳了三步,从交叉熵跳到了softmax之前
        dw2 = a1.T.dot(delta3)
        db2 = np.sum(delta3,axis=0,keepdims=True)
        delta2 = delta3.dot(w2.T)*(1-np.power(a1,2))  #tanh求导
        dw1 = np.dot(x.T,delta2)
        db1 = np.sum(delta2,axis=0)

        w1 -= learning_rate*dw1
        b1 -= learning_rate * db1
        w2 -= learning_rate * dw2
        b1 -= learning_rate * db1

        #画图
        loss = calculate_loss(model)
        axes = plt.gca()
        axes.cla()
        axes.set_title(f'iteration:{i},loss:{round(loss,3)}')
        axes.scatter(x[:,0],x[:,1],c=y)
        plt.pause(2)

        model = {'w1': w1, 'b1': b1, 'w2': w2, 'b2': b2}
        # print(model)
        print(calculate_loss(model))
    return  model
build_model(hidden_dim=10)


在这里插入图片描述

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值