1.逻辑斯谛分布
二项逻辑斯谛回归模型是一种分类模型, 由条件概率分布 P ( X ∣ Y ) P(X|Y) P(X∣Y)表示,形式为参数化的逻辑斯谛分布。这里随机变量取实数。随机变量 Y Y Y取值为1或者0.
1.1 LR二分类模型
P
(
Y
=
1
∣
x
)
=
exp
(
w
⋅
x
)
1
+
exp
(
w
⋅
x
)
=
exp
(
w
⋅
x
)
/
exp
(
w
⋅
x
)
(
1
+
exp
(
w
⋅
x
)
)
/
(
exp
(
w
⋅
x
)
)
=
1
e
−
(
w
⋅
x
)
+
1
P
(
Y
=
0
∣
x
)
=
1
1
+
exp
(
w
⋅
x
)
=
1
−
1
1
+
e
−
(
w
⋅
x
)
=
e
−
(
w
⋅
x
)
1
+
e
−
(
w
⋅
x
)
\begin{aligned} P(Y=1 | x) &=\frac{\exp (w \cdot x)}{1+\exp (w \cdot x)} \\ &=\frac{\exp (w \cdot x) / \exp (w \cdot x)}{(1+\exp (w \cdot x)) /(\exp (w \cdot x))} \\ &=\frac{1}{e^{-(w \cdot x)}+1} \\ P(Y=0 | x) &=\frac{1}{1+\exp (w \cdot x)} \\ &=1-\frac{1}{1+e^{-(w \cdot x)}} \\ &=\frac{e^{-(w \cdot x)}}{1+e^{-(w \cdot x)}} \end{aligned}
P(Y=1∣x)P(Y=0∣x)=1+exp(w⋅x)exp(w⋅x)=(1+exp(w⋅x))/(exp(w⋅x))exp(w⋅x)/exp(w⋅x)=e−(w⋅x)+11=1+exp(w⋅x)1=1−1+e−(w⋅x)1=1+e−(w⋅x)e−(w⋅x)
所以说上面的logistic回归就是一个线性分类模型,它与线性回归的不同点在于:为了将线性回归输出的很大范围的数,例如从负无穷到正无穷,压缩到0和1之间,这样的输出值表达为“可能性”才能说服广大民众。当然了,把大值压缩到这个范围还有个很好的好处,就是可以消除特别冒尖的变量的影响(不知道理解的是否正确)。而实现这个伟大的功能其实就只需要平凡一举,也就是在输出加一个logistic函数。另外,对于二分类来说,可以简单的认为:如果样本x属于正类的概率大于0.5,那么就判定它是正类,否则就是负类。实际上,SVM的类概率就是样本到边界的距离,这个活实际上就让logistic regression给干了。
在对模型参数进行估计时,可以应用极大似然估计法估计模型参数,从而得到逻辑斯谛回归模型:
L
(
w
)
=
log
∏
i
=
1
N
[
π
(
x
i
)
]
y
i
[
1
−
π
(
x
i
)
]
1
−
y
i
=
∑
i
=
1
N
[
y
i
log
(
π
(
x
i
)
)
+
(
1
−
y
i
)
log
(
1
−
π
(
x
i
)
)
]
=
∑
i
=
1
N
[
y
i
log
(
π
(
x
i
)
1
−
π
(
x
i
)
)
+
log
(
1
−
π
(
x
i
)
)
]
=
∑
i
=
1
N
[
y
i
(
w
⋅
x
i
)
−
log
(
1
+
exp
(
w
⋅
x
i
)
)
]
\begin{aligned} L(w) =\log \prod_{i=1}^{N}\left[\pi\left(x_{i}\right)\right]^{y_{i}}\left[1-\pi\left(x_{i}\right)\right]^{1-y_{i}} &=\sum_{i=1}^{N}\left[y_{i} \log \left(\pi\left(x_{i}\right)\right)+\left(1-y_{i}\right) \log \left(1-\pi\left(x_{i}\right)\right)\right] \\ &=\sum_{i=1}^{N}\left[y_{i} \log \left(\frac{\pi\left(x_{i}\right)}{1-\pi\left(x_{i}\right)}\right)+\log \left(1-\pi\left(x_{i}\right)\right)\right] \\ &=\sum_{i=1}^{N}\left[y_{i}\left(w \cdot x_{i}\right)-\log \left(1+\exp \left(w \cdot x_{i}\right)\right)\right] \end{aligned}
L(w)=logi=1∏N[π(xi)]yi[1−π(xi)]1−yi=i=1∑N[yilog(π(xi))+(1−yi)log(1−π(xi))]=i=1∑N[yilog(1−π(xi)π(xi))+log(1−π(xi))]=i=1∑N[yi(w⋅xi)−log(1+exp(w⋅xi))]
这样,问题就变成了以对数似然那个函数为目标的最优化问题,通过求解极大值
L
(
w
)
L(w)
L(w)函数,从而得到参数
w
w
w的值。一般通过转化为求解极小值,进而通过使用梯度下降法来更新参数。
1.2 LR 多分类模型
1.逻辑斯谛回归模型是由以下条件概率分布表示的分类模型。逻辑斯谛回归模型可以用于二类或多类分类。
P
(
Y
=
k
∣
x
)
=
exp
(
w
k
⋅
x
)
1
+
∑
k
=
1
K
−
1
exp
(
w
k
⋅
x
)
,
k
=
1
,
2
,
⋯
,
K
−
1
P(Y=k | x)=\frac{\exp \left(w_{k} \cdot x\right)}{1+\sum_{k=1}^{K-1} \exp \left(w_{k} \cdot x\right)}, \quad k=1,2, \cdots, K-1
P(Y=k∣x)=1+∑k=1K−1exp(wk⋅x)exp(wk⋅x),k=1,2,⋯,K−1
P ( Y = K ∣ x ) = 1 1 + ∑ k = 1 K − 1 exp ( w k ⋅ x ) P(Y=K | x)=\frac{1}{1+\sum_{k=1}^{K-1} \exp \left(w_{k} \cdot x\right)} P(Y=K∣x)=1+∑k=1K−1exp(wk⋅x)1
这里, x x x为输入特征, w w w为特征的权值。
逻辑斯谛回归模型源自逻辑斯谛分布,其分布函数 F ( x ) F(x) F(x)是 S S S形函数。逻辑斯谛回归模型是由输入的线性函数表示的输出的对数几率模型。
代码演示:
from math import exp
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
class LR_Classifer:
def __init__(self, max_iter = 200, learning_rate = 0.01):
self.max_iter = max_iter
self.learning_rate = learning_rate
def sigmoid(self, x):
return 1/(1 + exp(-x))
def dat_matrix(self, X):
data_mat = []
for d in X:
data_mat.append([1.0, *d])#追加数据到指定的列表当中
return data_mat
def fit(self, X, y):
data_mat = []
data_mat = self.dat_matrix(X)
#print(data_mat)
#print(len(data_mat[0]))
self.weights =np.zeros((len(data_mat[0]), 1), dtype=np.float32)
#print(self.weights)
for iter_ in range(self.max_iter):
for i in range(len(X)):
result = self.sigmoid(np.dot(data_mat[i], self.weights))
error = y[i] -result
self.weights += self.learning_rate * error * np.transpose([data_mat[i]])
print("Result: ", result)
print("LR_model(learning rate = {}, max_iter = {})".format(self.learning_rate, self.max_iter))
def score(self, X_test, y_test):
right = 0
X_test = self.dat_matrix(X_test)
print(len(X_test))
for x, y in zip(X_test, y_test):
result = np.dot(x, self.weights)
#print(result)
if (result > 0 and y == 1) or (result < 0 and y == 0):
right += 1
return right/len(X_test)
# data
def create_data():
iris = load_iris()
df = pd.DataFrame(iris.data, columns=iris.feature_names)
df['label'] = iris.target
df.columns = ['sepal length', 'sepal width', 'petal length', 'petal width', 'label']
data = np.array(df.iloc[:100, [0,1,-1]])
# print(data)
return data[:,:2], data[:,-1]
if __name__ == "__main__":
X, y = create_data()
X_train, X_test, y_train, y_test = train_test_split(X, y , test_size = 0.3 )
lr_clf = LR_Classifer()
lr_clf.fit(X_train, y_train)
lr_clf.score(X_test, y_test)
lr_clf.weights
代码结果:
Result: 0.9894921837831687
LR_model(learning rate = 0.01, max_iter = 200)
30
array([[-0.90014833],
[ 3.4473245 ],
[-5.692265 ]], dtype=float32)
绘图代码:
x_points = np.arange(4, 8)
y_ =-(lr_clf.weights[1] * x_points + lr_clf.weights[0])/lr_clf.weights[2]
print(y_)
plt.plot(x_points, y_)
plt.scatter(X[:50, 0],X[:50, 1], label = "0")
plt.scatter(X[50:, 0],X[50:, 1], label = "1")
plt.legend().
结果:
2. 最大熵模型
2.1最大熵原理
最大熵原理是概率模型学习的一个准则。最大熵原理认为,学习概率模型时,在所有可能的概率模型(分布)中,熵最大的模型是最好的模型.通常用约束条件来确定概率模型的集,所以,最大熵原理也可以表述为在满足约束条件的模型集合中选取熵最大的模型。原文如下:
Model all that is known and assume nothing about that which is unknown. In other words, given a collection of facts, choose a model which is consistent with all the facts, but otherwise as uniform as possible.
– Berger, 1996
最大熵原理概括如下:
- 等概率表示了对事实的无知,因为没有更多的信息,这种判断是合理的。
- 最大熵原理认为要选择的概率模型首先必须满足已有的事实,即约束条件
- 最大熵原理根据已有的信息(约束条件),选择适当的概率模型
- 最大熵原理认为不确定的部分都是等可能的,通过熵的最大化来表示等可能性。
- 最大熵的原则,承认已有的,且对未知无偏
- 最大熵原理并不直接关心特征选择,但是特征选择是非常重要的,因为约束可能是成千上万的。
2.2 最大熵模型的定义
假设分类模型是一个条件概率分布, P ( Y ∣ X ) P(Y|X) P(Y∣X), X ∈ X ⊆ R n X\in \mathcal {X} \sube \mathbf R^n X∈X⊆Rn,给定一个训练集 T = { ( x 1 , y 1 ) , ( x 2 , y 2 ) , … , ( x N , y N ) } T=\{(x_1, y_1), (x_2, y_2), \dots, (x_N, y_N)\} T={(x1,y1),(x2,y2),…,(xN,yN)}
N N N是训练样本容量, x ∈ R n x \in \mathbf R^n x∈Rn ,联合分布 P ( X , Y ) P(X,Y) P(X,Y)与边缘分布P(X)的经验分布分别为 P ~ ( X , Y ) 和 P ~ ( X ) \widetilde P(X, Y)和\widetilde P(X) P (X,Y)和P (X):
P
~
(
X
=
x
,
Y
=
y
)
=
ν
(
X
=
x
,
Y
=
y
)
N
P
~
(
X
=
x
)
=
ν
(
X
=
x
)
N
\begin{aligned} &\widetilde P (X=x, Y=y)=\frac{\nu(X=x, Y=y)}{N} \\ &\widetilde P (X=x)=\frac {\nu (X=x)}{N} \end{aligned}
P
(X=x,Y=y)=Nν(X=x,Y=y)P
(X=x)=Nν(X=x)
上面两个就是不同的数据样本,在训练数据集中的比例。
如果增加 n n n个特征函数, 就可以增加 n n n个约束条件,特征也对应增加了一列。
假设满足所有约束条件的模型集合为 C ≡ { P ∈ P ∣ E P ( f i ) = E P ~ ( f i ) , i = 1 , 2 , … , n } \mathcal {C} \equiv \ \{P \in \mathcal {P}|E_P(f_i)=E_{\widetilde {P}}(f_i) {, i=1,2,\dots,n}\} C≡ {P∈P∣EP(fi)=EP (fi),i=1,2,…,n},定义在条件概率分布 P ( Y ∣ X ) P(Y|X) P(Y∣X)上的条件熵为 H ( P ) = − ∑ x , y P ~ ( x ) P ( y ∣ x ) log P ( y ∣ x ) H(P)=-\sum \limits _{x, y} \widetilde {P}(x)P(y|x)\log {P(y|x)} H(P)=−x,y∑P (x)P(y∣x)logP(y∣x)则模型集合KaTeX parse error: Undefined control sequence: \cal at position 1: \̲c̲a̲l̲ ̲{C}中条件熵 H ( P ) H(P) H(P)最大的模型称为最大熵模型,上式中对数为自然对数。特征函数 f ( x , y ) f(x,y) f(x,y)关于经验分布 P ~ ( X , Y ) \widetilde P (X, Y) P (X,Y)的期望值用 E P ~ ( f ) E_{\widetilde P}(f) EP (f)表示
E
P
~
(
f
)
=
∑
x
,
y
P
~
(
x
,
y
)
f
(
x
,
y
)
E_{\widetilde P}(f)=\sum\limits_{x,y}\widetilde P(x,y)f(x,y)
EP
(f)=x,y∑P
(x,y)f(x,y)
特征函数
f
(
x
,
y
)
f(x,y)
f(x,y)关于模型
P
(
Y
∣
X
)
P(Y|X)
P(Y∣X)与经验分布
P
~
(
X
)
\widetilde P (X)
P
(X)的期望值, 用
E
P
(
f
)
E_{P}(f)
EP(f)表示
E P ( f ) = ∑ x , y P ~ ( x ) P ( y ∣ x ) f ( x , y ) E_{P}(f)=\sum\limits_{x,y}{\widetilde P(x)P(y|x)f(x,y)} EP(f)=x,y∑P (x)P(y∣x)f(x,y)
如果模型能够获取训练数据中的信息,那么就有
P
~
(
x
,
y
)
=
P
(
y
∣
x
)
P
~
(
x
)
\widetilde{P}(x,y)=P(y|x)\widetilde{P}(x)
P
(x,y)=P(y∣x)P
(x)
就可以假设这两个期望值相等,即
E P ( f ) = E P ~ ( f ) E_P(f)=E_{\widetilde P}(f) EP(f)=EP (f)
上面这个也是约束方程
通过对已知训练集数据的分析,能够拿到联合分布的经验分布和边缘分布的经验分布。特征函数用来描述 f ( x , y ) f(x, y) f(x,y)描述输入 x x x和输出 y y y之间的某一事实。
f ( x , y ) = { 1 x 与 y 满 足 某 一 事 实 0 否 则 f(x,y) = \begin{cases} 1 & x与y满足某一事实\\ 0 & 否则 \end{cases} f(x,y)={10x与y满足某一事实否则
约束条件的构成:
最大熵定模型算法:
代码演示:
import math
from copy import deepcopy
class MaxEntrop:
#数据预处理
def __init__(self, EPS = 0.005):
self.samples =[]
self._Y = set()
self._numXY = {} #存放f(x, y)的存放次数
self._N = 0 #样本数目
self._Ep_ = []
self._xyID = {}#记录id编号
self._n = 0 #特征值(x, y)的个数
self.C = 0 #z最大特征数目
self._IDxy = {}
self._w = []
self._EPS = EPS #收敛条件
self._lastw = []
def loadData(self, dataset):
self._samples = deepcopy(dataset)
print(self._samples)
for items in self._samples:
y = items[0]
X = items[1:]
print(y, X)
self._Y.add(y) # 集合中y若已存在则会自动忽略
for x in X:
if (x, y) in self._numXY:
self._numXY[(x, y)] += 1
else:
self._numXY[(x, y)] = 1
#print("self._numXY", self._numXY)
self._N = len(self._samples)
self._n = len(self._numXY)
self._C = max([len(sample) - 1 for sample in self._samples])
print("self._c", self._C)
self._w = [0] * self._n
self._lastw = self._w[:]
self._Ep_ = [0] * self._n
for i, xy in enumerate(self._numXY): # 计算特征函数fi关于经验分布的期望
self._Ep_[i] = self._numXY[xy] / self._N #计算经验分布函数
self._xyID[xy] = i
self._IDxy[i] = xy
def _Zx(self, X):
zx = 0
for y in self._Y:
ss = 0
for x in X:
# print("-------------------")
# print("x = ", x)
if (x, y) in self._numXY:
ss += self._w[self._xyID[(x, y)]] #保证权值和特征函数一一对应
zx += math.exp(ss)
return zx
def _model_pyx(self, y, X):
zx = self._Zx(X)
ss = 0
for x in X:
if (x, y) in self._numXY:
ss += self._w[self._xyID[(x, y)]]
pyx = math.exp(ss) / zx
return pyx
def _model_ep(self, index): # 计算特征函数fi关于模型的期望
x, y = self._IDxy[index]
ep = 0
for sample in self._samples:
#print("sample : ", sample)
if x not in sample:
continue
pyx = self._model_pyx(y, sample)
ep += pyx / self._N
return ep
def _convergence(self):#判断模型是否收敛
for last, now in zip(self._lastw, self._w):
if abs(last - now) >= self._EPS:
return False
return True
def predict(self, X):
Z = self._Zx(X)
result = {}
for y in self._Y:
ss = 0
for x in X:
if (x, y) in self._numXY:
ss += self._w[self._xyID[(x, y)]]
pyx = math.exp(ss)/Z
result[y] = pyx
return result
def train(self, maxiter = 1000):
for loop in range(maxiter):
self._lastw = self._w[:]
#改进的迭代尺度算法(IIS)
for i in range(self._n):
ep = self._model_ep(i)
self._w[i] += math.log(self._Ep_[i]/ep)/self._C
print("w:",self._w)
if self._convergence():
break
if __name__ == "__main__":
dataset = [['no', 'sunny', 'hot', 'high', 'FALSE'],
['no', 'sunny', 'hot', 'high', 'TRUE'],
['yes', 'overcast', 'hot', 'high', 'FALSE'],
['yes', 'rainy', 'mild', 'high', 'FALSE'],
['yes', 'rainy', 'cool', 'normal', 'FALSE'],
['no', 'rainy', 'cool', 'normal', 'TRUE'],
['yes', 'overcast', 'cool', 'normal', 'TRUE'],
['no', 'sunny', 'mild', 'high', 'FALSE'],
['yes', 'sunny', 'cool', 'normal', 'FALSE'],
['yes', 'rainy', 'mild', 'normal', 'FALSE'],
['yes', 'sunny', 'mild', 'normal', 'TRUE'],
['yes', 'overcast', 'mild', 'high', 'TRUE'],
['yes', 'overcast', 'hot', 'normal', 'FALSE'],
['no', 'rainy', 'mild', 'high', 'TRUE']]
maxent = MaxEntrop()
x = ['overcast', 'mild', 'high', 'FALSE']
maxent.loadData(dataset)
maxent.train(1000)
print("准确率:%f"%(maxent.predict(x)["yes"]*100))
print("w",maxent._w)
代码结果:
准确率:99.999718
w [3.8083642640626567, 0.03486819339596017, 1.6400224976589863, -4.463151671894514, 1.7883062251202593, 5.3085267683086395, -0.13398764643967703, -2.2539799445450392, 1.484078418970969, -1.8909065913678864, 1.9332493167387288, -1.262945447606903, 1.725751941905932, 2.967849703391228, 3.9061632698216293, -9.520241584621717, -1.8736788731126408, -3.4838446608661995, -5.637874599559358]
参考链接
LR算法
最大熵原理
李航·统计学习方法笔记·第6章 logistic regression与最大熵模型(2)·最大熵模型
逻辑回归(LR)个人学习总结篇