[从零开始机器学习]6.逻辑回归 非线性二分类

🐺本博主博客:ζั͡ ั͡雾 ั͡狼 ั͡✾的博客

🎀专栏:机器学习

🎀专栏:爬虫

🎀专栏:OpenCV图像识别处理

🎀专栏:Unity2D


⭐本节课理论视频: :P33-P38逻辑回归

 ⭐本节课推荐笔记:吴恩达逻辑回归总结_蓝色的紫的博客

🐺机器学习通过文字描述是难以教学学会的,每一节课我会推荐这个理论的网课,一定要看上面的理论视频!一定要看上面的理论视频!一定要看上面的理论视频!所以我只是通过代码实现,并通过注释形式来详细讲述每一步的原因,最后通过画图对比的新式来看结果比较。

⭐机器学习推荐博主:GoAI的博客_CSDN博客-深度学习,机器学习,大数据笔记领域博主

😊如果你什么都不懂机器学习,那我推荐GoAI的入门文章:机器学习知识点全面总结_GoAI的博客-CSDN博客_机器学习笔记

 非线性逻辑回归,主要通过给出的俩个变量,构建出一个新的矩阵,这个矩阵的其他元代表给出的这俩个变量的高次数。再根据上一节课的步骤做出来就行。主要需要注意最后得到的K系数矩阵对应的变量的次方。这个代码我也没写的太好,到更高次通用性不好,但由于写出一个通用性代码太费时间了,就直接拿二次函数和三次函数举例就行,如果你感兴趣,你可以根据规律,构建一个有规律的矩阵,并规律的给它乘上相应的回归得到的系数k,构建出我们最后的决策界限和假设函数

(1)二次函数回归分界线

import numpy as np
import matplotlib.pyplot as plt

# 全局变量

# 生成数据
#X每一行代表了x1,x2的值,并且相应对应下面y的分类
X =np.array([[0,1],
             [1,1],
             [1,0],
             [1,2],
             [2,1],
             [3,0],
             [0,3],
             [2,2],
             [2,3]])
# Y中的数据量等于X矩阵的行数,二分类,Y只能取0,1
Y = np.array([0,0,0,1,1,0,0,0,1])

#构造模拟的曲线次方
power=2
#获取变量默认为俩个变量
for i in range(power+1):
    for j in range(power+1):
        #通过俩个变量x1,x2构建高次函数
        if(i+j<=power&i+j>1):
            newX=np.power(X[:,0],i)*np.power(X[:,1],j)
            print("x1次方",i,"x2次方",j)
            X=np.append(X,np.array([newX]).T,axis=1)




# 开始
# 学习率,在代价函数斜率线上移动的距离步子大小
A = 0.1
# 迭代次数
time = 100000

# 进行归一化操作
# 获取每列平均值
u = np.average(X, axis=0)
# 获取没列的标准差
s = np.std(X, axis=0)
# 按行复制,构成X同形状矩阵
U = np.repeat([u], len(X), axis=0)
S = np.repeat([s], len(X), axis=0)
# 归一化,注意归一化所求的系数矩阵K是(X-U)/S的系数,真正系数,需要将x参数前面的系数合并
X= (X - U) / S


# X矩阵中第一列加入x0=1参数,便于构建常数项
X = np.insert(X, 0, np.ones((1, len(X))), axis=1)

# 数据个数
m = len(X)
# 参数个数
n = len(X[0])
# 系数变量K矩阵就是多元参数的系数,就是我们要递归的重点变量,先给这个矩阵的每个值都赋予初始值1
K = np.ones(n)
# 输出
print(f"有{n}个参数,就是X列数+常数项所乘的单位1")
print(f"有{m}条数据,就是加常数后X行数")
# 假设函数
# 在逻辑回归中我们设定的假设函数是H=1/(1+e^(-KX))这个值在0-1之间,可以当作概率

def H(Xi):
    global K
    y=np.dot(K, Xi.T)
    if y>0:
        return 1/(1+np.power(np.e,-y))  # xi需要转置,才能得到内积和
    else:#为负数的时候,对sigmoid函数的优化,避免了出现极大的数据溢出
        return np.power(np.e, y) / (1 + np.power(np.e, y))

# 代价函数L=求和((H(x)-y(x))^2),其中H是关于K矩阵中所有系数参数的函数
# 代价函数就是你估算的值与实际值的差的大小,使得代价函数最小,这样就能不断逼近结果
# 使得代价函数最小,就要使得初始点在斜率线上不断往低处移动,呈现出系数的不断微小移动
# 固定公式格式,推导原理看吴恩达P11
def dL_K():  # 代价函数对矩阵中系数参数k求导
    global X, Y, K, m, n
    dL_Karr = np.empty(n)  # 数组用来存放L对每个k求导后的结果
    for j in range(n):
        ans = 0
        for i in range(m):
            ans += ((H(X[i]) - Y[i]) * X[i][j])  # 由于k的系数是x,所以求导后还要乘x
        dL_Karr[j] = ans

    return dL_Karr


def itreation(time):  # 迭代,使O1,O2的代价函数趋于最低点
    global K

    for i in range(time):
        # 一次迭代过程中代价函数对系数k的导数数组
        dL_Karr = dL_K()
        # 同时变化,减法原因是正斜率使得O更小,负斜率使得O更大,不断往低处移动即代价函数最小
        K = K - A * dL_Karr
        if (i % 10000 == 0):  # 每100次输出一次
            print(f"迭代了{i}次,变量的系数矩阵K为{K}")

if __name__ == "__main__":
    print("X",X)
    print("Y",Y)
    itreation(time)

    print('归一化系数(第一个是常数)', K, )
    # 注意归一化所求的系数矩阵K是(X-U)/S的系数,真正系数,需要将x参数前面的系数合并
    #计算真正的X
    X[:,1:]=(X[:,1:]+U)*S
    # 忽略前一位常数,计算真正系数
    K[1:] = K[1:] / s
    # 利用真正系数,计算真正常数
    K[0] = K[0] - np.sum(K[1:] * u)
    print('真正系数矩阵', K)

    #绘图,注意x轴是确定参数x1,y轴是确定参数x2
    x1=X[:, 1]
    x2=X[:, 2]
    #画出决策界线,分界线是x2作为y轴,x1作为x轴,KX=0的线
    #构造网络
    x=np.linspace(-1,5,1000)
    y = np.linspace(-1, 5, 1000)
    x,y=np.meshgrid(x,y)
    z=K[0]+K[1]*x+K[2]*y+K[3]*y*y+K[4]*x*y+K[5]*x*x
    plt.contour(x,y,z,0)

    plt.scatter(x1[Y==0], x2[Y==0],c='r',marker='x')
    plt.scatter(x1[Y==1], x2[Y==1],c='g',marker='o')
    plt.xlabel("x1")
    plt.ylabel("x2")

    plt.show()

(2)三次函数回归分界线

import numpy as np
import matplotlib.pyplot as plt

# 全局变量

# 生成数据
#X每一行代表了x1,x2的值,并且相应对应下面y的分类
X =np.array([[0,1],
             [1,1],
             [1,0],
             [1,2],
             [2,1],
             [3,0],
             [0,3],
             [2,2],
             [2,3]])
# Y中的数据量等于X矩阵的行数,二分类,Y只能取0,1
Y = np.array([0,0,0,1,1,0,0,0,1])

#构造模拟的曲线次方
power=3
#获取变量默认为俩个变量
for i in range(power+1):
    for j in range(power+1):
        #通过俩个变量x1,x2构建高次函数
        if(i+j<=power&i+j>1):
            newX=np.power(X[:,0],i)*np.power(X[:,1],j)
            print("x1次方",i,"x2次方",j)
            X=np.append(X,np.array([newX]).T,axis=1)




# 开始
# 学习率,在代价函数斜率线上移动的距离步子大小
A = 0.1
# 迭代次数
time = 100000

# 进行归一化操作
# 获取每列平均值
u = np.average(X, axis=0)
# 获取没列的标准差
s = np.std(X, axis=0)
# 按行复制,构成X同形状矩阵
U = np.repeat([u], len(X), axis=0)
S = np.repeat([s], len(X), axis=0)
# 归一化,注意归一化所求的系数矩阵K是(X-U)/S的系数,真正系数,需要将x参数前面的系数合并
X= (X - U) / S


# X矩阵中第一列加入x0=1参数,便于构建常数项
X = np.insert(X, 0, np.ones((1, len(X))), axis=1)

# 数据个数
m = len(X)
# 参数个数
n = len(X[0])
# 系数变量K矩阵就是多元参数的系数,就是我们要递归的重点变量,先给这个矩阵的每个值都赋予初始值1
K = np.ones(n)
# 输出
print(f"有{n}个参数,就是X列数+常数项所乘的单位1")
print(f"有{m}条数据,就是加常数后X行数")
# 假设函数
# 在逻辑回归中我们设定的假设函数是H=1/(1+e^(-KX))这个值在0-1之间,可以当作概率

def H(Xi):
    global K
    y=np.dot(K, Xi.T)
    if y>0:
        return 1/(1+np.power(np.e,-y))  # xi需要转置,才能得到内积和
    else:#为负数的时候,对sigmoid函数的优化,避免了出现极大的数据溢出
        return np.power(np.e, y) / (1 + np.power(np.e, y))

# 代价函数L=求和((H(x)-y(x))^2),其中H是关于K矩阵中所有系数参数的函数
# 代价函数就是你估算的值与实际值的差的大小,使得代价函数最小,这样就能不断逼近结果
# 使得代价函数最小,就要使得初始点在斜率线上不断往低处移动,呈现出系数的不断微小移动
# 固定公式格式,推导原理看吴恩达P11
def dL_K():  # 代价函数对矩阵中系数参数k求导
    global X, Y, K, m, n
    dL_Karr = np.empty(n)  # 数组用来存放L对每个k求导后的结果
    for j in range(n):
        ans = 0
        for i in range(m):
            ans += ((H(X[i]) - Y[i]) * X[i][j])  # 由于k的系数是x,所以求导后还要乘x
        dL_Karr[j] = ans

    return dL_Karr


def itreation(time):  # 迭代,使O1,O2的代价函数趋于最低点
    global K

    for i in range(time):
        # 一次迭代过程中代价函数对系数k的导数数组
        dL_Karr = dL_K()
        # 同时变化,减法原因是正斜率使得O更小,负斜率使得O更大,不断往低处移动即代价函数最小
        K = K - A * dL_Karr
        if (i % 10000 == 0):  # 每100次输出一次
            print(f"迭代了{i}次,变量的系数矩阵K为{K}")

if __name__ == "__main__":
    print("X",X)
    print("Y",Y)
    itreation(time)

    print('归一化系数(第一个是常数)', K, )
    # 注意归一化所求的系数矩阵K是(X-U)/S的系数,真正系数,需要将x参数前面的系数合并
    #计算真正的X
    X[:,1:]=(X[:,1:]+U)*S
    # 忽略前一位常数,计算真正系数
    K[1:] = K[1:] / s
    # 利用真正系数,计算真正常数
    K[0] = K[0] - np.sum(K[1:] * u)
    print('真正系数矩阵', K)

    #绘图,注意x轴是确定参数x1,y轴是确定参数x2
    x1=X[:, 1]
    x2=X[:, 2]
    #画出决策界线,分界线是x2作为y轴,x1作为x轴,KX=0的线
    #构造网络
    x=np.linspace(-1,5,1000)
    y = np.linspace(-1, 5, 1000)
    x,y=np.meshgrid(x,y)
    #每个k对应的规则在28行输出可以看出来,第一二三行已经确定
    z=K[0]+K[1]*x+K[2]*y+K[3]*np.power(y,2)+K[4]*np.power(y,3)+K[5]*x*y+K[6]*x*np.power(y,2)+K[7]*np.power(x,2)+K[8]*np.power(x,2)*y+K[9]*np.power(x,3)
    plt.contour(x,y,z,0)

    plt.scatter(x1[Y==0], x2[Y==0],c='r',marker='x')
    plt.scatter(x1[Y==1], x2[Y==1],c='g',marker='o')
    plt.xlabel("x1")
    plt.ylabel("x2")

    plt.show()

再给他加一个数据

import numpy as np
import matplotlib.pyplot as plt

# 全局变量

# 生成数据
#X每一行代表了x1,x2的值,并且相应对应下面y的分类
X =np.array([[0,1],
             [1,1],
             [1,0],
             [1,2],
             [2,1],
             [3,0],
             [0,3],
             [2,2],
             [2,3],
             [3,2]])
# Y中的数据量等于X矩阵的行数,二分类,Y只能取0,1
Y = np.array([0,0,0,1,1,0,0,0,1,1])

#构造模拟的曲线次方
power=3
#获取变量默认为俩个变量
for i in range(power+1):
    for j in range(power+1):
        #通过俩个变量x1,x2构建高次函数
        if(i+j<=power&i+j>1):
            newX=np.power(X[:,0],i)*np.power(X[:,1],j)
            print("x1次方",i,"x2次方",j)
            X=np.append(X,np.array([newX]).T,axis=1)




# 开始
# 学习率,在代价函数斜率线上移动的距离步子大小
A = 0.1
# 迭代次数
time = 100000

# 进行归一化操作
# 获取每列平均值
u = np.average(X, axis=0)
# 获取没列的标准差
s = np.std(X, axis=0)
# 按行复制,构成X同形状矩阵
U = np.repeat([u], len(X), axis=0)
S = np.repeat([s], len(X), axis=0)
# 归一化,注意归一化所求的系数矩阵K是(X-U)/S的系数,真正系数,需要将x参数前面的系数合并
X= (X - U) / S


# X矩阵中第一列加入x0=1参数,便于构建常数项
X = np.insert(X, 0, np.ones((1, len(X))), axis=1)

# 数据个数
m = len(X)
# 参数个数
n = len(X[0])
# 系数变量K矩阵就是多元参数的系数,就是我们要递归的重点变量,先给这个矩阵的每个值都赋予初始值1
K = np.ones(n)
# 输出
print(f"有{n}个参数,就是X列数+常数项所乘的单位1")
print(f"有{m}条数据,就是加常数后X行数")
# 假设函数
# 在逻辑回归中我们设定的假设函数是H=1/(1+e^(-KX))这个值在0-1之间,可以当作概率

def H(Xi):
    global K
    y=np.dot(K, Xi.T)
    if y>0:
        return 1/(1+np.power(np.e,-y))  # xi需要转置,才能得到内积和
    else:#为负数的时候,对sigmoid函数的优化,避免了出现极大的数据溢出
        return np.power(np.e, y) / (1 + np.power(np.e, y))

# 代价函数L=求和((H(x)-y(x))^2),其中H是关于K矩阵中所有系数参数的函数
# 代价函数就是你估算的值与实际值的差的大小,使得代价函数最小,这样就能不断逼近结果
# 使得代价函数最小,就要使得初始点在斜率线上不断往低处移动,呈现出系数的不断微小移动
# 固定公式格式,推导原理看吴恩达P11
def dL_K():  # 代价函数对矩阵中系数参数k求导
    global X, Y, K, m, n
    dL_Karr = np.empty(n)  # 数组用来存放L对每个k求导后的结果
    for j in range(n):
        ans = 0
        for i in range(m):
            ans += ((H(X[i]) - Y[i]) * X[i][j])  # 由于k的系数是x,所以求导后还要乘x
        dL_Karr[j] = ans

    return dL_Karr


def itreation(time):  # 迭代,使O1,O2的代价函数趋于最低点
    global K

    for i in range(time):
        # 一次迭代过程中代价函数对系数k的导数数组
        dL_Karr = dL_K()
        # 同时变化,减法原因是正斜率使得O更小,负斜率使得O更大,不断往低处移动即代价函数最小
        K = K - A * dL_Karr
        if (i % 10000 == 0):  # 每100次输出一次
            print(f"迭代了{i}次,变量的系数矩阵K为{K}")

if __name__ == "__main__":
    print("X",X)
    print("Y",Y)
    itreation(time)

    print('归一化系数(第一个是常数)', K, )
    # 注意归一化所求的系数矩阵K是(X-U)/S的系数,真正系数,需要将x参数前面的系数合并
    #计算真正的X
    X[:,1:]=(X[:,1:]+U)*S
    # 忽略前一位常数,计算真正系数
    K[1:] = K[1:] / s
    # 利用真正系数,计算真正常数
    K[0] = K[0] - np.sum(K[1:] * u)
    print('真正系数矩阵', K)

    #绘图,注意x轴是确定参数x1,y轴是确定参数x2
    x1=X[:, 1]
    x2=X[:, 2]
    #画出决策界线,分界线是x2作为y轴,x1作为x轴,KX=0的线
    #构造网络
    x=np.linspace(-1,5,1000)
    y = np.linspace(-1, 5, 1000)
    x,y=np.meshgrid(x,y)
    #每个k对应的规则在28行输出可以看出来,第一二三行已经确定
    z=K[0]+K[1]*x+K[2]*y+K[3]*np.power(y,2)+K[4]*np.power(y,3)+K[5]*x*y+K[6]*x*np.power(y,2)+K[7]*np.power(x,2)+K[8]*np.power(x,2)*y+K[9]*np.power(x,3)
    plt.contour(x,y,z,0)

    plt.scatter(x1[Y==0], x2[Y==0],c='r',marker='x')
    plt.scatter(x1[Y==1], x2[Y==1],c='g',marker='o')
    plt.xlabel("x1")
    plt.ylabel("x2")

    plt.show()

 

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ζั͡ ั͡雾 ั͡狼 ั͡✾

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值