【机器学习练习 2】 - 逻辑回归
这个笔记包含了以Python为编程语言的Coursera上机器学习的第二次编程练习。请参考 作业文件 详细描述和方程。
在这一次练习中,我们将要实现逻辑回归并且应用到一个分类任务。我们还将通过将正则化加入训练算法,来提高算法的鲁棒性,并用更复杂的情形来测试它。
逻辑回归
逻辑回归 虽然带有回归两个字实际上是分类。它是用于处理二分类问题的监督学习算法。在二分类问题中,输出变量的取值是两个类别之一,通常表示为0和1,其中1表示正类,0表示负类。在这个练习中,我们将实现逻辑回归并应用于两个不同的数据集。
在训练的初始阶段,我们将要构建一个逻辑回归模型来预测,某个学生是否被大学录取。设想你是大学相关部分的管理者,想通过申请学生两次测试的评分,来决定他们是否被录取。现在你拥有之前申请学生的可以用于训练逻辑回归的训练样本集。对于每一个训练样本,你有他们两次测试的评分和最后是被录取的结果。为了完成这个预测任务,我们准备构建一个可以基于两次测试评分来评估录取可能性的分类模型。
让我们从检查数据开始。
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
path = 'ex2data1.txt'
data = pd.read_csv(path, header=None, names=['Exam 1', 'Exam 2', 'Admitted'])
data.head()
Exam 1 | Exam 2 | Admitted | |
---|---|---|---|
0 | 34.623660 | 78.024693 | 0 |
1 | 30.286711 | 43.894998 | 0 |
2 | 35.847409 | 72.902198 | 0 |
3 | 60.182599 | 86.308552 | 1 |
4 | 79.032736 | 75.344376 | 1 |
让我们创建两个分数的散点图,并使用颜色编码来可视化,如果样本是正的(被接纳)或负的(未被接纳)。
positive = data[data['Admitted'].isin([1])]
negative = data[data['Admitted'].isin([0])]
fig, ax = plt.subplots(figsize=(12,8))
ax.scatter(positive['Exam 1'], positive['Exam 2'], s=50, c='b', marker='o', label='Admitted')
ax.scatter(negative['Exam 1'], negative['Exam 2'], s=50, c='r', marker='x', label='Not Admitted')
ax.legend()
ax.set_xlabel('Exam 1 Score')
ax.set_ylabel('Exam 2 Score')
plt.show()
看起来在两类间,有一个清晰的决策边界。现在我们需要实现逻辑回归,那样就可以训练一个模型来预测结果。方程实现在下面的代码示例在"exercises" 文件夹的 “ex2.pdf” 中。
sigmoid 函数
g 代表一个常用的逻辑函数(logistic function)为S形函数(Sigmoid function),公式为: g ( z ) = 1 1 + e − z g\left( z \right)=\frac{1}{1+{
{e}^{-z}}} g(z)=1+e−z1
合起来,我们得到逻辑回归模型的假设函数:
h θ ( x ) = 1 1 + e − θ T X {
{h}_{\theta }}\left( x \right)=\frac{1}{1+{
{e}^{-{
{\theta }^{T}}X}}} hθ(x)=1+e−θTX1
def sigmoid(z):
return 1 / (1 + np.exp(-z))
让我们做一个快速的检查,来确保它可以工作。
nums = np.arange(-10, 10, step=1) #creates a vector containing 20 values from -10 to 10
fig, ax = plt.subplots(figsize=(12,8))
ax.plot(nums, sigmoid(nums), 'r')
plt.show()
棒极了!现在,我们需要编写代价函数来评估结果。
代价函数:
J ( θ ) = 1 m ∑ i = 1 m [ − y ( i ) log ( h θ ( x ( i ) ) ) − ( 1 − y ( i ) ) log ( 1 − h θ ( x ( i ) ) ) ] J\left( \theta \right)=\frac{1}{m}\sum\limits_{i=1}^{m}{[-{
{y}^{(i)}}\log \left( {
{h}_{\theta }}\left( {
{x}^{(i)}} \right) \right)-\left( 1-{
{y}^{(i)}} \right)\log \left( 1-{
{h}_{\theta }}\left( {
{x}^{(i)}} \right) \right)]} J(θ)=m1i=1∑m[−y(i)log(hθ(x(i)))−(1−y(i))log(1−hθ(x(i)))]
def cost(theta, X, y):
theta = np.matrix(theta)
X = np.matrix(X)
y = np.matrix(y)
first = np.multiply(-y, np.log(sigmoid(X * theta.T))) #y=1 时,第二项为0
second = np.multiply((1 - y), np.log(1 - sigmoid(X * theta.T))) #y=0 时,第一项为0
return np.sum(first - second) / (len(X)) #求和
现在,我们要做一些设置,和我们在练习1在线性回归的练习很相似。
# add a ones column - this makes the matrix multiplication work out easier
data.insert(0, 'Ones', 1)
# set X (training data) and y (target variable)
cols = data.shape[1]
X = data.iloc[:,0:cols-1]
y = data.iloc[:,cols-1:cols]
# convert to numpy arrays and initalize the parameter array theta
X = np.array(X.values)
y = np.array(y.values)
theta = np.zeros(3)
让我们来检查矩阵的维度来确保一切良好。
theta #初始化的theta w1,w2,w3(b)
array([0., 0., 0.])
X.shape, theta.shape, y.shape
((100, 3), (3,), (100, 1))
让我们计算初始化参数的代价函数(theta为0)。
cost(theta, X, y)
0.6931471805599453
看起来不错,接下来,我们需要一个函数来计算我们的训练数据、标签和一些参数thata的梯度。
gradient descent(梯度下降)
- 这是批量梯度下降(batch gradient descent)
- 转化为向量化计算: 1 m X T ( S i g m o i d ( X θ ) − y ) \frac{1}{m} X^T( Sigmoid(X\theta) - y ) m1X