2021-03-13

多项式回归-

题目:对于文档“data.txt”中的数据(每一行表示一个样本,每一行有三个数值, 其中前两个值代表输入属性 x,最后一个值代表标签 y),请使用逻辑回归模型训练一个分类器,并对结果进行可视化(5分)。注 1:编程语言不限;注 2:可视化过程中,请使用不同颜色或形状区分“0”类和“1”类数据,并画出决策方程。
data.txt下载:https://pan.baidu.com/s/11-NOmNlIDXBDClYUEndhdg
(data中的数据是118行3列的数据,中间 ‘,’ 隔开,前两列是x,最后一列是标签)

首先先把数据集显示了一下,发现数据的分布如图所示
2021-03-13

蓝色点是标签为0的,橘色点是标签为1的,所以想要区分的话,训练一个直线的线性分类器的话,效果显然是不好的,所以需要用多项式回归去训练出一个类似图中紫色线的更好的决策曲线。
(*注:这是个平时的作业,所以也没将数据集分为train_data、validation_data和test_data,直接拿着数据集做了一个分类器,然后看看分类正确的有多少,作为了正确率)
1.load数据
loaddata的时候,为了训练曲线分类器,所以直接将train_data读取成了如下形式,[1, x1, x2, x12, x22, x1x2] shape[1 ,6]

def loaddata(filename):
    file =  open(filename)
    x = []
    y = []
    for line in  file.readlines():
        line = line.strip().split(',')
        x.append([1, float(line[0]), float(line[1]), float(line[0]) * float(line[0]),
                        float(line[1]) * float(line[1]), float(line[0]) * float(line[1])])
        # 将给定的数据x1,x2 升维为 [1, x1, x2, x1^2, x2^2, x1*x2]
        y.append(float(line[-1]))
    file.close()
    return x,y

2.梯度下降


def w_calc(x, y, alpha = 0.001, maxIter = 500):
    xmat = np.mat(x)
    ymat = np.mat(y).T
    initial = 0.1 # 线性变化学习率的初始学习率
    z = matIter/initial + 1 
    #w init
    w = np.mat(np.random.randn(1, 6))
    #print(np.shape(w))
    wT = w.T
    #w updata
    for i in range(maxIter + 1):
        #做个一个线性变化的学习率,开始比加大,后来比较小
        alpha = -i/z + initial #如果将本行注释掉,那么将使用0.001不变的学习率
        #alpha =  4/(1.0 +  i) + 0.01 #另一种曲线变化的学习率
        H = 1 / (1 + np.exp(-xmat * wT))
        dcos_dw = xmat.T * (H - ymat)
        #cost函数对w的求导
        #print(dcos_dw)
        wT -= alpha * dcos_dw
        #wT加减都可以,只要与上面的wT-ymat对应起来就可以 如果上面是ymat-wT, 那么这里用 wT += alpha * dcos_dw就可以
    return wT

3.动态学习率与不变学习率之间的对比

变化学习率 500 epochs的训练效果:
2021-03-13
2021-03-13
0.001不变学习率 200 epochs的训练效果:
2021-03-13
2021-03-13

完整代码:

'''跑的时候换一下data.txt的路径'''
import numpy as np
import matplotlib.pyplot as plt
import math
#def loaddata
def loaddata(filename):
    file =  open(filename)
    x = []
    y = []
    for line in  file.readlines():
        line = line.strip().split(',')
        x.append([1, float(line[0]), float(line[1]), float(line[0]) * float(line[0]),
                        float(line[1]) * float(line[1]), float(line[0]) * float(line[1])])
        y.append(float(line[-1]))
    file.close()
    return x,y
#w
def w_calc(x, y, alpha = 0.001, maxIter = 500):
    xmat = np.mat(x)
    ymat = np.mat(y).T
    #w init
    w = np.mat(np.random.randn(1, 6))
    #print(np.shape(w))
    wT = w.T
    #w updata
    for i in range(maxIter + 1):
        #做个一个线性变化的学习率,开始比加大,后来比较小
        alpha = -i/5001+0.1
        #alpha =  4/(1.0 +  i) + 0.01
        H = 1 / (1 + np.exp(-xmat * wT))
        dcos_dw = xmat.T * (H - ymat)
        #print(dcos_dw)
        wT -= alpha * dcos_dw
    return wT

def plot_decision_line(weight,x,y):
    xmat = np.mat(x)
    ymat = np.mat(y)

    fig = plt.figure()
    ax = fig.add_subplot(111)
    # 原始数据集画出来
    ax.scatter(xmat[:,1][ymat.T == 0].A, xmat[:,2][ymat.T == 0].A, marker='.', label="label = 0")
    ax.scatter(xmat[:,1][ymat.T == 1].A, xmat[:,2][ymat.T == 1].A, marker='+', label="label = 1")
    X = np.arange(-1.0, 1.0, 0.1)
    Y = np.arange(-1.0, 1.0, 0.1)
    x, y = np.meshgrid(X, Y)
    # 椭圆公式
    z = weight[0] + weight[1] * x + weight[2] * y + weight[3] * x * x + weight[4] * y * y + weight[5] * x * y
    ax.contour(x, y, z, [0])
    plt.xlabel('X1')
    plt.ylabel('X2')
    plt.grid()
    plt.legend()
    plt.show()

def accuracy(w, x, y):
    # 计算准确率
    m, n = np.shape(x)
    acc = 0
    dataMat = np.mat(x)
    labelMat = np.mat(y)
    labelMatT = labelMat.T
    #print(np.shape(labelMatT))
    #print(np.shape(dataMat[0]),np.shape(weights))
    for i in range(m):
        if 1 / (1 + np.exp(-dataMat[i] * w)) > 0.5:
            label = 1
        else:
            label = 0
        if label == labelMatT[i]:
            acc = acc + 1
    #print("acc_num = ", acc_num)
    # 计算f1
    tp = 0
    fn = 0
    fp = 0
    tn = 0
    for j in range(m):
        if labelMatT[j] == 1:
            if 1 / (1 + np.exp(-dataMat[i] * w)) > 0.5:
                tp = tp + 1
            else:
                fn = fn + 1
        else:
            if 1 / (1 + np.exp(-dataMat[i] * w)) > 0.5:
                fp = fp + 1
            else:
                tn = tn + 1
    p = tp / (tp+fp)
    r = tp / (tp+fn)
    f1 = 2*p*r / (p+r)
    return acc / m, f1



if __name__ == '__main__':
    # implement
    x, y = loaddata('E:/data.txt')
    #跑的时候换一下data.txt的路径
    w = w_calc(x, y)
    #print(w)
    weight = []
    for i in range(0, 6):
        weight.append(w[i, 0])
    plot_decision_line(weight, x, y)
    print("(acc, F1):", accuracy(w, x, y))

上一篇:算法提高课-图论-负环-AcWing 361. 观光奶牛:spfa判正环、负环、01分数规划、二分


下一篇:windows 判断端口被哪个程序占用