当前位置:   article > 正文

逻辑回归 手写代码笔记(python)_基于data.txt手写逻辑回归代码

基于data.txt手写逻辑回归代码

逻辑回归

前言

建议先了解线性回归,本文记录自己学习过程,不涉及具体理论

过程

导包

import numpy as np
import matplotlib.pyplot as plt
  • 1
  • 2

获取数据
数据是网上找的,下载链接,点我
就是100条数据,属性:坐标x, 坐标y, 类别

filePath = 'dataSet.txt' # 路径自己改
data = [line.strip() for line in open(filePath)]
data = data[:5] # 只拿前5条做示范
print(data)
  • 1
  • 2
  • 3
  • 4

在这里插入图片描述
将x, y, label用列表提出

x = []
y = []
label = []
for d in data:
    dList = d.split(' ')
    x.append(float(dList[0]))
    y.append(float(dList[1]))
    label.append(int(dList[2]))
print(x, y, label)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

在这里插入图片描述

画图
把这些点画出来

i = 0
for item in label:
    if item == 0:
        plt.scatter(x[i], y[i], color = 'red') # 第一类用红点
    elif item == 1:
        plt.scatter(x[i], y[i], color = 'green') # 第二类用绿点
    i += 1
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

在这里插入图片描述
数据处理
由于后面有矩阵运算,用列表的话涉及很多for循环,所以将list类型转为np类型,更简便

# 数据处理,列表转为np形式
x = np.concatenate([x])
x = x.reshape(len(x), 1)

y = np.concatenate([y])
y = y.reshape(len(x), 1)
# 把y加入x
x = np.hstack((x, y))
# X 加一列全是1的矩阵
ones = np.ones((len(x), 1))
x = np.hstack((x, ones))
# label同理
label = np.concatenate([label])
label = label.reshape(len(x),1)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

细节说明:

print(x, type(x))
x = np.concatenate([x])
print(x, type(x))
  • 1
  • 2
  • 3

在这里插入图片描述

x.reshape(len(x), 1)
# 将x从一个1×m的矩阵->m × 1矩阵(列向量)
np.hstack((x, y))
# 指x,y这两个列向量融合,变为m × 2矩阵
  • 1
  • 2
  • 3
  • 4

注意,此处易错,x,y都是特征,所以都要放入特征矩阵。再加入一列全1,是为了偏置值(看看理论推导就懂了,笔者第一次做时,以为y不是特征,弄了一下午,结果错得很离谱~)

逻辑回归部分

def LogisticRegression(x, label):
    num = 1000                       	  #迭代1000轮
    W = np.array([0, 0, 0]).reshape(3, 1) # W权重系数,初始化0,列向量
    alpha = 0.01                   		  # 学习率
    predict = sigmoid(x, W)           	  # 预测值
    gradient = getGradient(x, label, predict)# 计算梯度,代码简单,背后公式推导比较长
    for i in range(num):
        W = W - alpha * gradient		  # 梯度下降做法,更新权重系数W
        predict = sigmoid(x, W)			  # 重复上面操作
        gradient = getGradient(x, label, predict)
    return W
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

预测函数sigmoid

def sigmoid(x, W):
    z = np.dot(x, W) # np.dot是点积,即z = w0*x1 + w1*y1 + w2*1,z也是列向量
    return 1 / (1 + np.exp(-z))  # 返回的是预测值,也是列向量
  • 1
  • 2
  • 3

X = ( x 1 y 1 1 x 2 y 2 1 . . . x m y m 1 ) W = ( w 0 w 1 w 2 ) Z = X W = ( w 0 x 1 + w 1 y 1 + w 2 . . . w 0 x m + w 1 y m + w 2 ) X =

(x1y11x2y21...xmym1)
W =
(w0w1w2)
\\ Z=XW =
(w0x1+w1y1+w2...w0xm+w1ym+w2)
X=x1x2...xmy1y2ym111W=w0w1w2Z=XW=w0x1+w1y1+w2...w0xm+w1ym+w2

计算梯度
梯度下降的函数,和线性回归相似但不同
W = W − α X T ( p r e d i c t − t r u e ) W= W - \alpha X^T(predict - true) W=WαXT(predicttrue)
X是特征矩阵,predict,true分别为 预测值,真实值 的列向量
X T ( p r e d i c t − t r u e ) X^T(predict - true) XT(predicttrue) 就是我们要算的梯度
数学推导来源---->这里

def getGradient(x, label, predict):
	# 前面除的是为了均值,不重要
    gradient = (1./len(label)) * (np.dot(np.transpose(x), (predict - label)))
    return gradient
  • 1
  • 2
  • 3
  • 4

画线
最后就是画出我们的分割线啦,通过不断地梯度下降,得到了一组很好的权重系数W,它就是系数

x1 = np.linspace(-5, 5, 100)   #创建一个等差数列,用于画图的x点
y1 = (W[0]*x1 + W[2]) / -W[1]  # w[0]*x+ w[1]*y + w[2] = 0, 求解y (x,y其实就是x1, y1)
plt.plot(x1, y1)			   # 画直线
  • 1
  • 2
  • 3

结果如图:
在这里插入图片描述

完整代码:

import numpy as np
import matplotlib.pyplot as plt

# 数据获取
def createDataSet():
    filePath = 'dataSet.txt'
    data = [line.strip() for line in open(filePath)]
    x = []
    y = []
    label = []
    for d in data:
        dList = d.split(' ')
        #print(dList)
        x.append(float(dList[0]))
        y.append(float(dList[1]))
        label.append(int(dList[2]))
    drawScatter(x, y, label)
    x ,label = dataProcess(x, y, label)
    print(f'{len(x)}条数据')
    return x, label

def dataProcess(x, y, label):
    # 数据处理,列表转为np形式
    x = np.concatenate([x])
    x = x.reshape(len(x), 1)

    y = np.concatenate([y])
    y = y.reshape(len(x), 1)
    x = np.hstack((x, y))
    
    #X与一个len1行1列的矩阵合并
    ones = np.ones((len(x), 1))
    x = np.hstack((x, ones))
    
    label = np.concatenate([label])
    label = label.reshape(len(x),1)
    return x, label
    
# 画点
def drawScatter(x, y, label):
    i = 0
    for item in label:
        if item == 0:
            plt.scatter(x[i], y[i], color = 'red')
        elif item == 1:
            plt.scatter(x[i], y[i], color = 'green')
        i += 1
    
def sigmoid(x, W):
    z = np.dot(x, W) # np.dot是点积
    return 1 / (1 + np.exp(-z))

def getGradient(x, label, predict):
    gradient = (1./len(label)) * (np.dot(np.transpose(x), (predict - label)))
    return gradient

def LogisticRegression(x, label):
    num = 10000                       #迭代10000轮
    W = np.array([0, 0, 0]).reshape(3, 1)
    alpha = 0.01                      # 学习率
    predict = sigmoid(x, W)             # 预测值
    #print('预测值 ', predict)
    gradient = getGradient(x, label, predict)
    #print('梯度 ', gradient)
    for i in range(num):
        W = W - alpha * gradient
        predict = sigmoid(x, W)
        gradient = getGradient(x, label, predict)
    return W

if __name__ == '__main__':
    x, label = createDataSet()
    W = LogisticRegression(x, label)
    # 画线
    x1 = np.linspace(-5, 5, 100)
    y1 = (W[0]*x1 + W[2]) / -W[1]
    plt.plot(x1, y1)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77

参考文章

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家自动化/article/detail/279367?site
推荐阅读
相关标签
  

闽ICP备14008679号