Machine Learning(Andrew) ex2-Logistic Regression
椰汁笔记
Logistic Regression
- 1.1 Visualizing the data
可视化数据的第一步就是读入数据,数据形式和作业相同都是txt文件。
第一列为第一门课程的成绩,第二列为第二门课程的成绩。读入方式仍然是按行读入,进行分离转换。发现这样的数据读入总是存在因此,这里封装一个读取该种类型数据文件的函数。
def read_dataset(filename, type_tuple, separator=','):
"""
从文件中读入数据,文件的数据存储应该是每组数据存在一行并用分隔符隔开
返回列表存储
eg:
1.1,2.1,3.1
1.2,2.2,3.2
parameters:
----------
filename : str
(包括路径的)文件名
type_tuple : tuple
每一行数据的类型
separator : str
分隔符,默认为','
"""
f = open(filename, 'r')
lines = f.readlines()
data = []
if len(type_tuple) != len(lines[0]) and len(type_tuple) == 1:
for line in lines:
line = line[:-1]`在这里插入代码片`
line = line.split(sep=separator)
row = []
for col in line:
row.append(type_tuple[0](col))
data.append(row)
elif len(type_tuple) == len(lines[0].split(sep=separator)):
for line in lines:
line = line[:-1]
line = line.split(sep=separator)
row = []
for i in range(len(line)):
row.append(type_tuple[i](line[i]))
data.append(row)
else:
data = None
return data
要画出两种数据的散点图,我们需要根据y值将数据分为admitted和not admitted两组。同样我也实现了一个通用的方法
def separate_dataset(data, col, boundary):
"""
将数据按照某列进行二分类
parameters:
----------
data : ndarray
一组数据存在一行
col : int
分类标准应用到的列号
boundary : double
分类边界
"""
data0 = np.array(data)
data1 = np.array(data)
dc0 = 0
dc1 = 0
for i in range(data.shape[0]):
if data[i][col] < boundary:
data1 = np.delete(data1, i - dc1, axis=0)
dc1 += 1
else:
data0 = np.delete(data0, i - dc0, axis=0)
dc0 += 1
return data0, data1
将划分好的两组数据绘制散点图,matplotlib.pyplot.xlim()设置x坐标的范围,matplotlib.pyplot.legend()用于显示图例。
data = read_dataset("ex2data1.txt", (float, float, float), separator=',')
data0, data1 = separate_dataset(data, -1, 0.5)
plt.title("raw data scatter")
plt.xlabel("exam1 score")
plt.ylabel("exam2 score")
plt.xlim((20, 110))
plt.ylim((20, 110))
na = plt.scatter(data0[..., 0], data0[..., 1], marker='x', c='b', label='not admitted')
a = plt.scatter(data1[..., 0], data1[..., 1], marker='x', c='y', label='admitted')
plt.legend(handles=[na, a], loc="upper right")
- 1.2.1 Warmup exercise: sigmoid function
g ( z ) = 1 1 + e − z g(z)=\frac{1}{1+e^{-z}} g(z)=1+e−z1
sigmoid函数实现了将结果从R转化到0-1,用来表示概率。实现sigmoid函数,通过numpy库的支持很简单
def sigmoid(z):
return 1 / (1 + np.exp(-z))
- 1.2.2 Cost function and gradient
这里的损失函数不能继续使用平方代价函数,因为sigmoid函数会导致该损失函数变为非凸函数(存在多个局部最优解),进而导致梯度下降出现效果不好的问题。因此逻辑回归的损失函数更换为
J ( θ ) = 1 m ∑ i = 1 m [ − y ( i ) l o g ( h θ ( x ( i ) ) ) − ( 1 − y ( i ) ) l o g ( 1 − h θ ( x ( i ) ) ) ] J(\theta)=\frac{1}{m}\sum_{i=1}^{m}[-y^{(i)}log(h_{\theta}(x^{(i)}))-(1-y^{(i)})log(1-h_{\theta}(x^{(i)}))] J(θ)=m1i=1∑m[−y(i)log(hθ(x(i)))−(1−y(i))log(1−hθ(x(i)))]
h θ ( x ) = θ T X h_{\theta}(x)=\theta^TX h