机器学习——逻辑回归正则

本文主要实现非线性可分数据的逻辑回归,包括特征映射,正则化等

  • 原数据

原数据是关于是由2个特征和一个标签字段组成的资料,如果需要数据可以来“三行科创”微信公众号交流群索要。

原数据

  • 数据可视化

看看原数据有什么特点

import numpy as np 
import pandas as pd 
import matplotlib.pyplot as plt
data = pd.read_csv("CourseraML/ex2/data/ex2data2.txt", header = None, names = ["x1", "x2", "label"]) #读取数据
X = np.array(data[["x1", "x2"]]) #特征
y = np.array(data["label"]) #标签
X = np.insert(X, 0, 1, axis =1) #多插入虚拟列
m = len(X) #样本数
pos = np.array([X[i,:] for i in range(len(X)) if y[i]==1] ) #postive 特征
neg = np.array([X[i,:] for i in range(len(X)) if y[i] ==0]) #negative 特征

def dataPlot(): #定义数据可视化函数
    #plt.figure(figsize = (6,4))
    plt.plot(pos[:,1], pos[:,2], "+", color = "orange", label = "positive")
    plt.plot(neg[:, 1], neg[:,2], "x", color = "red", label = "negative")
    plt.xlabel("x1")
    plt.ylabel("x2")
    plt.title("Scatter plot")
    plt.legend()
    
dataPlot()

数据分布图
从数据散点分布图可以看到正性样本主要分布在中间,负性样本主要分布在周边,没办法用一条直线来分离,故需要做特征映射

  • 特征映射

原始特征只有 x 1 , x 2 x_1,x_2 x1,x2可以用多项式创建更多的特征 x 1 、 x 2 、 x 1 x 2 、 x 1 2 、 x 2 2 、 x 1 2 x 2 、 . . . 、 x 1 n x 2 n x_1、x_2、x_1x_2、x_1^2、x_2^2、x_1^2x_2、... 、x_1^nx_2^n x1x2x1x2x12x22x12x2...x1nx2n来刻画,因为更多的特征进行逻辑回归时,得到的分割线可以是任意高阶函数的形状

def featureMap(x1col, x2col): #定义特征映射函数 非线性变换,变成线性可分的
    power = 6
    out = np.ones((x1col.shape[0], 1))
    for i in range(1, power+1):
        for j in range(0, i+1):
            term1 = x1col **(i-j)
            term2 = x2col**(j)
            term = (term1*term2).reshape(term1.shape[0], 1)
            out = np.hstack((out, term))
    return out
X_mapped = featureMap(X[:,1], X[:,2])
  • 损失函数和最优化

定义损失函数,并最优化参数theta

from scipy.special import expit #导入logistic函数
from scipy import optimize

def h(mytheta, myX): #定义假设函数
    return  expit(np.dot(myX, mytheta))

def costFunction(start_theta, msX, msy, mylambda = 0): #定义损失函数
    term1 = np.dot(-np.array(y).T, np.log(h(start_theta, msX)))
    term2 = -np.dot(1-np.array(y).T, np.log(1-h(start_theta, msX)))
    regterm = (mylambda/2)*(np.sum(np.dot(start_theta.T, start_theta)))
    return float((1./m)*(term1 + term2 + regterm))

initial_theta = np.zeros((X_mapped.shape[1], 1))
print(costFunction(initial_theta, X_mapped, y))

def optimizeRegularizedTheta(mytheta, myX, myy,mylambda = 0): #最优化函数
    result = optimize.minimize(costFunction, mytheta, args = (myX, myy, mylambda), method = "BFGS", options = {
    
    "maxiter":500, "disp":False})
    return np.array([result.x]), result.fun

theta, mincost = optimizeRegularizedTheta(initial_theta, X_mapped, y)
print(theta, mincost)

此时的输出

[[   19.4138306     31.3285252     16.12163907  -189.01000144
    -82.69573059   -98.31203217  -230.13312921  -193.14282274
   -123.96034243   -40.47214451   647.53238059   493.01458645
    803.48109078   328.58433644   178.55338966   391.62472251
    512.68088072   610.14918783   356.83374407   122.25968739
     34.66926026  -755.58675051  -882.12281602 -1486.20826842
  -1024.42073137 -1002.80938001  -367.67179237  -120.41821974]] 

0.24862169044212865

前面一个矩阵是theta值,此时的theta是特征映射后的theta,0.2486……是最小损失函数值

  • 决策边界

需要定义出决策边界并可视化,此时的决策函数

f ( x 1 , x 2 ) = f ( x 1 、 x 2 、 x 1 x 2 、 x 1 2 、 x 2 2 、 . . . x 1 n x 2 n ) f(x_1,x_2)= f(x_1、x_2、x_1x_2、x_1^2、x_2^2、... x_1^nx_2^n) f(x1,x2)=f(x1x2x1x2x12x22...x1nx2n)

是一个关于 x 1 , x 2 x_1, x_2 x1,x2的高程函数,故可以用等值线来刻画决策边界,可以认为lambda是一个超参,取不同的正则化参数lambda来观看分割效果。

def boundaryPlot(mytheta, myX, myy, mylambda =0): #定义绘制决策边界函数
    theta, mincost = optimizeRegularizedTheta(mytheta, myX, myy, mylambda)
    xvals = np.linspace(-1, 1.5, 50)
    yvals = np.linspace(-1, 1.5, 50)
    zvals = np.zeros((len(xvals), len(yvals)))
    for i in range(len(xvals)):
        for j in range(len(yvals)):
            myfeatureij = featureMap(np.array([xvals[i]]), np.array([yvals[j]]))
            zvals[i][j] = np.dot(theta, myfeatureij.T)
    zvals = zvals.transpose()
    
    u, v = np.meshgrid(xvals, yvals)
    mycontour = plt.contour(xvals, yvals, zvals, [0])
    myfmt = {
    
    0:"Lambda = %d"%mylambda}
    plt.clabel(mycontour, inline =1 ,fontsize = 15, fmt = myfmt)
    plt.title("Decision boundary")

plt.figure(figsize = (9,9))
plt.subplot(221)
dataPlot()
boundaryPlot(theta, X_mapped, y, 0)

plt.subplot(222)
dataPlot()
boundaryPlot(theta, X_mapped, y, 1)

plt.subplot(223)
dataPlot()
boundaryPlot(theta, X_mapped, y ,10)

plt.subplot(224)
dataPlot()
boundaryPlot(theta, X_mapped, y, 100)
   

延伸阅读

机器学习——逻辑回归(一)

机器学习——多元线性回归模型

机器学习——单变量线性回归模型

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/zengbowengood/article/details/107330723