从零开始的机器学习0-基础知识及线性回归
基础知识至线性回归一些问题与概念线性回归的Python实现及测试线性回归线性回归模型损失函数最速下降法
数据预处理(numpy)读取文件numpy中的矩阵调整ndarray中的数据类型转化标准化矩阵调用
基础知识至线性回归
从头学习周志华版的机器学习,同时准备使用Python实现一些相关的方法,以及一些小的项目。因为Python是新手,也准备借这次机会熟悉并掌握,代码方面有一些笨拙,希望慢慢改进、进步。
一些问题与概念
1、机器学习的概念是什么?机器学习学的是什么?
机器学习通过计算的手段利用经验(通常为数据)来改善系统自身性能。
研究的主要内容是关于计算机上从数据中产生“模型”的算法,即“学习算法”。P1
2、什么叫做泛化能力,我们可以通过哪些途径增强我们训练出的模型的泛化能力?
学得模型适用于新样本的能力成为“泛化能力”。
假设样本服从一个未知的分布
D
\mathcal{D}
D,得到关于
D
\mathcal{D}
D的信息越多,泛化能力越强。通常可以增加训练样本数目,保证每个样本是独立地从这个分布上采样获得。
3、假设空间与版本空间的区别与联系是什么?
假设空间:该问题所有假设组成的空间,即所有假设的集合。
版本空间:在假设空间中与训练集一致的假设的集合。
版本空间是属于假设空间的。
4、归纳偏好的概念以及它的作用是什么?
机器学习过程中对某类型假设的偏好称为“归纳偏好”。
因为训练集对应的版本空间包含的假设可能不唯一,对于某个具体的学习算法必须产生一个模型,这时学习算法的归纳偏好会确定采用哪个假设(有种做决策的感觉),可以看作学习算法对假设进行选择的启发式或“价值观”。
5、什么是过拟合、欠拟合?如何避免这些情况?
过拟合:将训练样本的某些自身特点(训练样本多有的)当作了所有潜在样本都会具有的一般性质。
欠拟合:与过拟合相对,指对训练样本的一般性质尚未学习好。
处理欠拟合:在决策树学习中扩展分支,在神经网络学习中增加训练轮次。
处理过拟合:控制模型复杂度,增加训练样本数目。
6、什么是交叉验证?什么时候要使用交叉验证?为什么?
交叉验证将数据集D划分为k个大小相似的互斥子集,使每个子集尽可能保持数据分布的一致性(即从D中采用分层采样得到)。然后每次将k-1子集作为训练集,剩下的1个作为测试集,进行k次训练和测试,返回k个测试结果的均值。
作用:对学习器的泛化误差进行评估。
可以增加评估结果的稳定性和保真性(跟k有关)。
7、如何评价模型性能?常用的性能指标有哪些,写出公式?
使用“性能度量”的方式。下面公式中D为样例集,m为样例个数,xi和yi分别为第i个样本及其对应的真实标记。
1)均方误差:
E
(
f
;
D
)
=
1
m
∑
i
=
1
m
(
f
(
x
i
)
−
y
i
)
2
E(f;D)=\frac{1}{m}\sum^{m}_{i=1}(f({\bm x}_i)-y_i)^2
E(f;D)=m1∑i=1m(f(xi)−yi)2
对于数据分布
D
\mathcal{D}
D和概率分布函数
p
(
⸱
)
p(⸱)
p(⸱):
E
(
f
;
D
)
=
1
m
∫
x
−
D
(
f
(
x
)
−
y
)
2
p
(
x
)
d
x
E(f;\mathcal{D})=\frac{1}{m}\int_{{\bm x}-\mathcal{D}}(f({\bm x})-y)^2p({\bm x})d{\bm x}
E(f;D)=m1∫x−D(f(x)−y)2p(x)dx
2)错误率:
E
(
f
;
D
)
=
1
m
∑
i
=
1
m
Γ
(
f
(
x
i
)
≠
y
i
)
2
E(f;D)=\frac{1}{m}\sum^{m}_{i=1}\Gamma(f({\bm x}_i)\neq y_i)^2
E(f;D)=m1∑i=1mΓ(f(xi)̸=yi)2
精度:
acc
(
f
;
D
)
=
1
m
∑
i
=
1
m
Γ
(
f
(
x
i
)
=
y
i
)
2
=
1
−
E
(
f
;
D
)
\textrm{acc}(f;D)=\frac{1}{m}\sum^{m}_{i=1}\Gamma(f({\bm x}_i)= y_i)^2=1-E(f;D)
acc(f;D)=m1∑i=1mΓ(f(xi)=yi)2=1−E(f;D)
8、偏差与方差是什么?过拟合,欠拟合,分别对应偏差与方差的什么情况?
令
y
D
y_D
yD为
x
{\bm x}
x在数据集中的标记,
f
ˉ
(
)
\bar f()
fˉ()为学习算法的期望预测。
方差:
v
a
r
(
x
)
=
E
D
[
(
f
(
x
;
D
)
−
f
ˉ
(
x
)
)
2
]
var({\bm x})= \mathbb{E}_D[(f(\bm{x};D)-\bar f (\bm{x}))^2]
var(x)=ED[(f(x;D)−fˉ(x))2]
噪声:
ε
2
=
E
D
[
(
y
D
−
y
)
2
]
\varepsilon^2= \mathbb{E}_D[(y_D-y)^2]
ε2=ED[(yD−y)2]
偏差:期望输出与真实标记的差别:
v
a
r
(
x
)
=
E
D
[
(
f
ˉ
(
x
)
−
y
)
2
]
var({\bm x})= \mathbb{E}_D[(\bar f(\bm{x})-y)^2]
var(x)=ED[(fˉ(x)−y)2]
欠拟合时偏差大(主导),过拟合时方差大(主导)。
9、特征归一化是什么?为什么要归一化?常用的归一化方法有哪些?
不同评价指标往往具有不同的量纲和量纲单位,这样的情况会影响到数据分析的结果,为了消除指标之间的量纲影响,需要进行数据标准化处理(特征归一化),以解决数据指标之间的可比性。原始数据经过数据标准化处理后,各指标处于同一数量级,适合进行综合对比评价。
线性函数归一化(Min-Max Scaling):将原始数据进行线性的变换,并确保新的数据均映射到[0,1]区间内,实现对原始数据的等比缩放:
X
n
r
o
m
=
X
−
X
m
i
n
X
m
a
x
−
X
m
i
n
X_{nrom}=\frac{X-X_{min}}{X_{max}-X_{min}}
Xnrom=Xmax−XminX−Xmin
0均值归一化(Standardization):将原始数据均映射到均值为0,标准差为1的分布上。具体来说,假设原始特征的均值为μ、标准差为σ,那么归一化公式定义为:
z
=
x
−
μ
σ
z=\frac{x-\mu}{\sigma}
z=σx−μ
10、什么是梯度下降算法?写出具体公式,解释小批量随机梯度下降,随机梯度下降
梯度下降法(用到梯度的确定型最优化算法):梯度可以反映函数下降的陡峭程度,梯度下降算法沿着函数最陡峭(梯度最小)的方向往前走一定步长,反复此过程直至找到最优解。
随机梯度下降(Stochastics Gradient Descent, SGD):每次迭代只计算一个样本的损失函数(loss),再逐步遍历所有样本。特点:局部震荡,总体收敛。
小批量随机梯度下降(mini-batch SGD):为了兼顾稳定下降和随机特性以及小计算量。每次迭代选取总体样本中的一小批样本计算损失函数,逐步遍历所有样本。
线性回归的Python实现及测试
线性回归
线性回归模型
一般的线性方程
f
(
x
)
=
w
1
x
1
+
w
2
x
2
+
.
.
.
+
w
n
x
n
+
b
f(x)=w_1x_1+w_2x_2+...+w_nx_n+b
f(x)=w1x1+w2x2+...+wnxn+b 写成向量形式
⇒
f
(
x
)
=
w
T
x
+
b
\Rightarrow f(\bm{x})= \bm{w} ^T\bm{x}+b
⇒f(x)=wTx+b
线性回归 线性回归使用一般的线性方程做回归,即为处理的数据
X
\textbf{X}
X建立一个合适的线性模型,也就是说需要确定一组合适的
w
\bm{w}
w和
b
b
b。值得注意的是将
X
\textbf{X}
X中的每组数据
x
i
\bm{x}_i
xi替换为
x
^
i
=
(
x
i
;
1
)
\hat{\bm{x}}_i=(\bm{x}_i;1)
x^i=(xi;1),则可以将
w
\bm{w}
w和
b
b
b用
w
^
=
(
w
;
b
)
\hat{\bm{w}}=(\bm{w};b)
w^=(w;b)代替。模型可以替换为
f
(
x
^
i
)
=
w
^
T
x
i
f(\hat{\bm{x}}_i)= \hat{\bm{w} }^T\bm{x}_i
f(x^i)=w^Txi。在Python中:
'''线性回归模型'''
def modelLR(x
, w
):
fx
= dot
(x
, w
)
return fx
模型合不合适可以根据
f
(
x
)
f(x)
f(x)和真实的
y
y
y之间的差距来判断,通常我们使用损失函数衡量它们之间差距。
损失函数
均方误差是在线性回归问题中常用的损失函数,写成:
L
=
1
m
∑
i
=
1
m
(
f
(
x
i
)
−
y
)
2
L=\frac{1}{m}\sum^{m}_{i=1}(f(\bm{x}_i)-y)^2
L=m1i=1∑m(f(xi)−y)2 通常我们认为损失函数越小,模型越合适,也就是说模型的求解转化为了一个最优化问题,在这个问题中目标函数是损失函数,决策变量为
w
^
\hat{\bm{w} }
w^。(基于均方误差最小化来进行模型求解的方法称为最小二乘法)
'''损失函数'''
def lossFun(w
, x
, y
):
funError
= 0
x
= mat
(x
)
for i
in range(0, size
(y
, 0)):
x1
= x
[i
, :]
y1
= y
[i
, 0]
fx
= modelLR
(x1
, w
)
funError
+= (fx
- y1
)**2
return funError
/size
(y
, 0)
最速下降法
有了优化问题就需要优化方法,回归问题中通常使用梯度下降法,它需要确定两样东西:方向和步长。 我使用的是最速下降法,方向
d
k
d_k
dk为梯度的负方向: 下面是梯度方向的计算
'''计算梯度'''
def calcGrad(h
, x
, y
, w
):
dkCol
= size
(w
, 0)
dk
= ones
((1, dkCol
))
for i
in range(0, size
(w
, 0)):
w1
= w
.copy
()
w2
= w
.copy
()
w1
[i
] = w1
[i
] - h
w2
[i
] = w2
[i
] + h
y1
= lossFun
(w1
, x
, y
)
y2
= lossFun
(w2
, x
, y
)
dk
[0, i
] = (y2
-y1
)/(2*h
)
return dk
步长:精确法为:
α
k
=
arg
min
α
≥
0
f
(
w
^
k
+
α
d
k
)
\alpha_k=\arg \min\limits_{\alpha\geq0}f(\hat{\bm{w}} _k+\alpha d_k)
αk=argα≥0minf(w^k+αdk) 其中:
α
k
\alpha_k
αk需要满足:
ϕ
′
(
α
)
=
d
d
w
^
k
f
(
w
^
k
+
α
d
k
)
∣
α
=
α
k
=
∇
f
(
w
^
k
+
α
k
d
k
)
T
d
k
=
0
\phi'(\alpha)=\frac{\rm{d}}{{\rm d}\hat{\bm{w}} _k}f(\hat{\bm{w}} _k+\alpha d_k)|_{\alpha=\alpha_k}=\nabla f(\hat{\bm{w}} _k+\alpha_k d_k)^Td_k=0
ϕ′(α)=dw^kdf(w^k+αdk)∣α=αk=∇f(w^k+αkdk)Tdk=0
'''计算步长'''
def calcStep(dk
, x
, y
, w
):
ak
= 1
for i
in range(0, 20):
newF
= lossFun
(w
+ak
*dk
, x
, y
)
oldF
= lossFun
(w
, x
, y
)
if (newF
<oldF
):
break
else:
ak
= ak
/2
return ak
整体的最速下降法为:
'''最速下降法训练'''
def steepest(x
, y
, w
):
epsilon
= 1e-5
h
= 1e-5
maxIter
= 1e3
for i
in range(0, int(maxIter
)):
grad
= calcGrad2
(h
, x
, y
, w
)
dk
= -grad
.T
ak
= calcStep
(dk
, x
, y
, w
)
neww
= w
+ ak
*dk
if abs(lossFun
(neww
, x
, y
)-lossFun
(w
, x
, y
)) <= epsilon
:
break
w
= neww
return w
, lossFun
(w
, x
, y
)
数据预处理(numpy)
一个numpy中的 矩阵运算方法帖子
读取文件
path
= "D:/事项/机器学习学习/week1/"
train
= pd
.read_csv
(path
+ 'train.csv', engine
='python', encoding
='gbk')
test
= pd
.read_csv
(path
+ 'test.csv', engine
='python', encoding
='gbk')
yt
= pd
.read_csv
(path
+ 'answer.csv', engine
='python', encoding
='gbk')
setTrainX
= train
.values
setTestX
= test
.values
setTrainX
[setTrainX
== "NR"] = 0
setTestX
[setTestX
== "NR"] = 0
此时读取出的文件为panda的DataFrame格式,通过DataFrame.values可以得到ndarray格式的数据。
numpy中的矩阵调整
使用hstack(A, B) 横向结合两个矩阵,需要保证AB矩阵列数相等;vstack(A, B)纵向结合两个矩阵,需要保证AB矩阵行数相等。 因为在这次数据处理中需要循环着结合矩阵,启动时需要有一个矩阵,使用empty(a, b)产生的矩阵并不会被覆盖,所以用了一个很蠢的办法:
tempX
= ones
((18, 1))
for i
in range(0, size
(setTrainX
, 0) - 18, 18):
tempXX
= setTrainX
[i
:i
+18, :]
tempX
= hstack
((tempX
, tempXX
))
tempX
= tempX
[:, 1:]
ndarray中的数据类型转化
矩阵形式的ndarray的数据不能使用强制类型转换的方法改变数据类型,它的数据类型可以通过ndarray.dtype查看,直接更改dtype会引起数据的解释错误,即内存中存储的内容不变,仅改变了解释方式。 接着上面的处理,目前的数据的dtype为 “U32” 是字符串类型,不能参与运算,需要改为浮点型,此时需要用到 ndarray.astype(type) 函数。
x
= x
.astype
(float)
值得注意的是,参数float实际上是转换为 “float64” 类型(默认的浮点类型)。
标准化
标准化会影响算法的收敛速度。
ss
= StandardScaler
()
for i
in range(0, size
(x
, 1)):
ss
.fit
(x
[:, i
].reshape
(-1, 1))
x
[:, i
] = ss
.transform
(x
[:, i
].reshape
(-1, 1)).T
注意ndarray格式的数据需要 .reshape(-1, 1) 才能使用 .fit() 函数,原因暂时不知道
矩阵调用
ndarray下的向量似乎不能使用类似A[a, b]的调用方法,但是用mat(A)转化为matrix类型就可以使用了。