Ng-机器学习(Day 3)

Logistic 多分类问题:

面对Logistic多分类问题,通常的分类是将一类单独拎出来,然后其他剩下的分为另一类。这样就可以利用二元Logistic回归的思路了。

比如下图,我们一共有三个类,那么我们会有三个分类器,然后依此计算hypothesis函数的值,最后看那个类别下的h值最大,那么就将其归为这一类。
在这里插入图片描述在这里插入图片描述

过拟合问题:

简单来说,过拟合就是指一个模型在训练集上表现的相当好(代价函数可能非常的接近于0 ),但是在测试集上的表现比较差,无法准确的进行预测。

下图中,图1:可见一元的线性方程无法较好的去拟合这个房价的模型(因为,房价在随着大小的增加越来越趋向于稳定,但是这个模型拟合的线是没有表现出来稳定的趋势的。),因此我们可以叫这种现象为“欠拟合(Under fitting)”或“高偏差(High bias)”; 图3 可以看到是一个高阶的模型,它拟合出来的线是由很多上下波动的,这可以叫“过度拟合(Over fitting)”或“高方程”.
在这里插入图片描述

解决:

  1. 减少特征数量
  2. 正则化
    概念:
    通过惩罚模型中参数的方法来,使得模型变的平滑。

看下图的这个例子。
在这里插入图片描述
原来的模型当中theta_3,theta_4分别是x的三次和x的四次的参数。因为高阶的存在,会使得我们的模型变得弯弯扭扭。那么我们如果希望这个模型和左边的那个相似应该怎么做呢?

那必然是要减少theta_3和theta_4对于模型的影响!减少到theta_3和theta_4几乎等于0(就好像被这两项被去掉了一样,这样我们就可以得到一个近似左图的模型了。)

那么怎么做呢?

我们可以在后面添加两项,如下图。
在这里插入图片描述
因为我们期望这个代价函数得到最小值,那么我们肯定不希望前面系数为1000的theta_3和theta_4大,而是要这两个参数尽可能的小,从而我们的theta_3,和theta_4对于整个模型的影响就会减小,使我们得到一个比较平滑模型。

上面的例子当中,我们知道想要惩罚哪一项,但是当我们的特征数量非常多的时候,我们往往无法知道我们需要惩罚哪些特征项。

因此,利用正则化来缩小出来theta_0外的所有的参数
在这里插入图片描述

这里的lambda就是正则化参数,它是用来控制两个目标的取舍的。
第一个目标:更好的拟合数据
第二个目标:使得参数尽可能的小

在这里插入图片描述
注:当lambda过大,可能就会对所有的参数惩罚过大,最后就的h函数可能就成为下面这样了。。
在这里插入图片描述

线性回归正则化:

  • 梯度下降法:
    我们将上面讨论到的正则化方法加入到梯度下降函数当中,那么我们求偏导之后的结果就如下图所示。
    其中alpha*(lamda/m)是一个很小很小的正数,所以说,每次更新一次参数,那么我们的theta就会是原来的theta*比一小一点点的数,再减去后面的那项。
    在这里插入图片描述
  • 正规方程法:
    在原来的基础上增加一个lambda*一个对角矩阵(假设矩阵为A,那么A11就是0,对角线其他值都为1)
    在这里插入图片描述
    对于不可逆问题:
    利用正则化,只要保证lambda>0,那么就可以使得矩阵可逆。
    在这里插入图片描述

Logistic 回归正则化:

  • 代价函数
    在这里插入图片描述
  • 梯度下降
    在这里插入图片描述

Logistic回归 正则化实例:

  • 首先读取数据,查看数据分布情况
import pandas as pd 
import numpy as np
from matplotlib import pyplot as plt 
import seaborn as sns
Data = pd.read_csv('E:/Data/Ng/Coursera-ML-AndrewNg-Notes-master/code/ex2-logistic regression/ex2data2.txt',names=['exam1','exam2','accepted'])
Data.head(30)

sns.set(context='notebook',style='ticks',font_scale = 1.5)
sns.lmplot('exam1','exam2',hue = 'accepted',data=Data,height = 6,fit_reg=False,scatter_kws={'s':50})
plt.title('Regularized Logistic Regression')
plt.show()

结果如下:
从散点分布情况来看,这个条决策线应当是一个近似圆形的线才能分割。
在这里插入图片描述
在这里插入图片描述

  • 因为目前读取的数据最高只有一次项,所以要写一个函数来进行转化数据。
def feature_mapping(x,y,power,as_ndarray=False):
    """将函数转化为高阶,把两个特征值转化为多个特征值
    polynomial expansion法"""
    data = {'f{}{}'.format(i-p,p) : np.power(x,i-p)*np.power(y,p)
           for i in np.arange(power+1)
           for p in np.arange(i+1)}
    if as_ndarray:
        return np.array(pd.DataFrame(data))
    else:
        return pd.DataFrame(data)
x1 = np.array(Data['exam1'])
x2= np.array(Data['exam2'])
data = feature_mapping(x1,x2,power=6)
print(data.shape)
data.head()

注意根据两个数值可以看出是几次方:
f00:x10 * x20
f10: x11 * x20
f20: x12 * x20
所以根据输入power值多少,就可以计算到几次方,这样就可以应用到我们的正则化当中的。
在这里插入图片描述

  • 定义必要的函数:

在这里插入图片描述

def get_y(Data):
    return np.array(Data.iloc[:,-1])

def sigmoid(z):
    return 1/(1+np.exp(-z))

在这里插入图片描述

def gradient(theta,x,y):
    return (1/len(x))* x.T@ (sigmoid(x@theta)-y)

在这里插入图片描述

def cost(theta, X, y):
    return np.mean(-y * np.log(sigmoid(X @ theta)) - (1 - y) * np.log(1 - sigmoid(X @ theta)))

在这里插入图片描述

def regcost(theta,x,y,l=1):
    m = len(x)
    theta_j1_jn = theta[1:] #首先新建一个theta函数,因为theta0不需要处理,所以取出theta1到n即可
    regularized_term = (l/(2*m))* np.power(theta_j1_jn,2).sum() #根据公式计算出正则化项
    return cost(theta,x,y)+regularized_term

在这里插入图片描述

def reg_descent(theta,x,y,l=1):
    theta_j1_jn = theta[1:]
    regularized_theta = (l/len(x))*theta_j1_jn #正则化项
    regularized_term = np.concatenate([np.array([0]),regularized_theta]) #因为theta_0不动,这时候要将其组合回去
    return gradient(theta,x,y) + regularized_term
  • 利用scipy.optimize的minimize来进行拟合
import scipy.optimize as ops
theta = np.zeros(data.shape[1])
X = feature_mapping(x1,x2,power=6,as_ndarray=True)
y = get_y(Data)
res = ops.minimize(fun = regcost,x0 = theta,args=(X,y),method='Newton-CG',jac=reg_descent)
res

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

  • 测试精确度
X = feature_mapping(x1,x2,power=6,as_ndarray=True)
y = get_y(Data)

res = ops.minimize(fun = regcost,x0 = theta,args=(X,y),method='Newton-CG',jac=reg_descent)

def pred_y(final_theta,x):
    prob = sigmoid(x@final_theta)
    test = []
    for each in prob:
        if each>0.5:
            test.append(1)
        else:
            test.append(0)
    return test

final_theta = res.x
pred = pred_y(final_theta,X)
print(classification_report(y,pred))

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

  • 绘制决策边界:
def feature_mapped_logistic_regression(power,l):
	"""获取最优拟合参数
	Params:
		power:函数最高次方
		l:lambda
	return:
		final_theta:最优拟合参数"""
    Data = pd.read_csv('E:/Data/Ng/Coursera-ML-AndrewNg-Notes-master/code/ex2-logistic regression/ex2data2.txt',names=['exam1','exam2','accepted'])
    x0 = np.array(Data['exam1'])
    x1 = np.array(Data['exam2'])
    y = get_y(Data)
    
    X = feature_mapping(x0,x1,power,as_ndarray=True) #获取高次方函数
    theta = np.zeros(X.shape[1])
    res = ops.minimize(fun=regcost,x0=theta,args=(X,y,l),method='TNC',jac=reg_descent) 
    final_theta = res.x
    
    return final_theta

def find_decision_boundary(density, power, theta, threshhold):
	""""找到最合适的参数
	目前理解的不太清楚,希望知道的朋友可以留言告诉我一下,谢谢!"""
    t1 = np.linspace(-1, 1.5, density) #因为我数据点都是分布在-1,1.5之间的,所以我取-1,1.5的等差数列密度为1000个,为了可以布满整个图像
    t2 = np.linspace(-1, 1.5, density)

    cordinates = [(x, y) for x in t1 for y in t2] #取得各个点的座标
    x_cord, y_cord = zip(*cordinates) #解压
    mapped_cord = feature_mapping(x_cord, y_cord, power)  # 进行高次运算

    inner_product = np.array(mapped_cord) @ theta 

    decision = mapped_cord[np.abs(inner_product) < threshhold] #增加条件

    return decision.f10, decision.f01 #获取x^1和y^1 用来画边界函数

def draw_boundury(power,l):
    density =1000
    threshhold= 2* 10**-3
    final_theta = feature_mapped_logistic_regression(power,l)
    x,y = find_decision_boundary(density, power, final_theta, threshhold)
    
    dt = pd.read_csv('E:/Data/Ng/Coursera-ML-AndrewNg-Notes-master/code/ex2-logistic regression/ex2data2.txt',names=['exam1','exam2','accepted'])
    sns.lmplot('exam1','exam2',hue = 'accepted',data=dt,height=6,fit_reg=False,scatter_kws={'s':50})
    
    plt.scatter(x,y,color='red',s=10)
    plt.title('Desicion Boundary')
    plt.show()

draw_boundury(power=6,l=1) 
draw_boundury(power=6,l=0) #过拟合
draw_boundury(power=6,l=50) #欠拟合

结果:
lambda=1比较合适
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章