机器学习1.0——线性模型、感知机
对一个机器学习的算法,最简单的框架就是:
1.输入
2.模型——这里简单的模型其实就是一个函数,我们的目标就是通过数据训练函数的参数(或者我们更熟悉的系数),估计参数的过程就是学习模型的过程
3.输出
文章目录
一、线性模型
拿简单问题举例
在分类问题中,线性分类模型解决某个东西属于哪一类,例如,给一张照片,判断是风景还是人像;经典的比如,判断一个瓜是好瓜还是坏瓜
在回归问题中,线性回归模型解决给定的数据对应的输出是多少,例如前面提到的,给了一套房的各种数据,预测这套房的价格。
最简单的是一元(单变量)线性回归y=ax+b,但是房价肯定不会被一个因素(属性/特征)决定,这就需要多元线性回归
输入变成x=(x1,x2,…,xd),d个属性(特征)
对应的,属性的权值(权重)为w=(w1,w2,…,wd),每个分量都代表对应特征对结果影响的大小。 这里默认都是列向量
- y=wTx+b
- 这里w和b就是模型的参数(系数)
拿房价举例,如果地理位置的权值比楼层、大小这些因素的权值都大,说明地理位置这个特征的变化,比其他特征变化对房价的影响更大
根据一元(单变量)线性回归 y=ax+b 展开聊聊
- 回顾往事,一次函y=ax+b中,a(斜率)决定倾斜程度,b(截距)决定与y轴交点
.
对一组真实的数据D={(x1,y1),(x2,y2),…,(xn,yn)},
其中,xi=(xi1,xi2,…,xid)
我们的目标是,确定模型f(x)=ax+b,输入xi,输出f(xi)
一、感知机(perceptron)——二分类模型
1.1 模型
- 输入空间——n维,某个实例的特征数据,维数取决于特征的个数
- 输出{+1,-1},这里是二分类,+1,-1根据模型的设置来设定,在应用里可以根据自己的需求和设计来定义
- 输入到输出的函数(模型/分类器)
f ( x ) = s i g n ( w x + b ) f(x)=sign(wx+b) f(x)=sign(wx+b)- 模型参数:w(权值),b(偏置)
不特别说明的时候这里都是向量
这里w是wx+b=0的法向量,具体超平面的定义不好理解的话,就记住把空间划分成两部分的分界- 二维理解,一条直线把二维平面分为两部分
- 高维空间,n维空间被n-1维空间分成两部分
前提:数据集线性可分
1.2 模型学习(w,b)
我们得到的模型,输入xi他的输出 f(xi)一定是个估计值,我们的目标就是让这个估计值无限接近于真实值,这个真实值就是数据集里xi对应的yi
数据集
D
=
{
(
x
1
,
y
1
)
,
(
x
2
,
y
2
)
,
.
.
.
,
(
x
n
,
y
n
)
}
D=\left \{ \left ( x_{1},y_{1} \right ), \left ( x_{2},y_{2} \right ) ,..., \left ( x_{n},y_{n} \right )\right \}
D={(x1,y1),(x2,y2),...,(xn,yn)}
损失函数
损失函数就是衡量这个模型的表现如何,我们的目标是正确分类,也可以说尽量少的误分类
- 设误分类的集合为M,感知机的损失函数用输入xi到分类器的距离来定义
L ( w , b ) = − ∑ x i ∈ M y i ( w ⋅ x i + b ) L(w,b)=-\sum_{x_{i}\in M }^{} y_{i} (w\cdot x_{i}+b ) L(w,b)=−xi∈M∑yi(w⋅xi+b)
细说
输入xi到分类器的距离(>0)(可以简单参考点到直线的距离公式):
∣
w
T
x
i
+
b
∣
∥
w
∥
\frac{\left | w^{T}x_{i}+b \right | } {\left \| w \right \| }
∥w∥
wTxi+b
如果误分类了,那么
y
i
(
w
T
x
i
+
b
)
<
0
y_{i}(w^{T}x_{i}+b ) <0
yi(wTxi+b)<0
y
i
∈
{
+
1
,
−
1
}
y_{i}\in \left \{ +1,-1 \right \}
yi∈{+1,−1}这是真实值,
w
T
x
i
+
b
w^{T}x_{i}+b
wTxi+b 是模型估计值,估计错了,那这两就异号了
以上,所有实例都分类正确的话,那损失函数值为0,模型表现嘎嘎好,损失函数值越大,模型越差
学习参数
根据上面的内容,问题从得到一个好的分类器到了让损失函数最小
m
i
n
w
,
b
L
(
w
,
b
)
=
−
∑
x
i
∈
M
y
i
(
w
⋅
x
i
+
b
)
\underset{w,b}{min} L(w,b)=-\sum_{x_{i}\in M }^{} y_{i} (w\cdot x_{i}+b )
w,bminL(w,b)=−xi∈M∑yi(w⋅xi+b)
这就是优化问题了,梯度下降出场,估计参数
▽
w
L
(
w
,
b
)
=
−
∑
x
i
∈
M
y
i
x
i
\bigtriangledown _{w}L(w,b)=-\sum_{x_{i}\in M }^{} y_{i}x_{i}
▽wL(w,b)=−xi∈M∑yixi
▽
b
L
(
w
,
b
)
=
−
∑
x
i
∈
M
y
i
\bigtriangledown _{b}L(w,b)=-\sum_{x_{i}\in M }^{} y_{i}
▽bL(w,b)=−xi∈M∑yi
然后更新参数,参数在算法开始会设定初始值,一般为0
这里随机梯度下降不用每次都用所有数据更新参数,随机选一个就可以,这样更快
w
n
e
w
⟶
w
o
l
d
+
η
y
i
x
i
w_{new} \longrightarrow w_{old}+\eta y_{i}x_{i}
wnew⟶wold+ηyixi
b
n
e
w
⟶
b
o
l
d
+
η
y
i
b_{new} \longrightarrow b_{old}+\eta y_{i}
bnew⟶bold+ηyi
一直更新,直到损失函数为0(在数据集可分的假设下,这是必然结果)
二、回归模型
其实回归上面已经差不多了,不过回归的损失函数一般是均方误差或者变形
L
(
w
,
b
)
=
∑
i
(
f
(
x
i
)
−
y
i
)
2
L(w,b)=\sum_{i }^{} (f( x_{i})-y_{i} )^{2}
L(w,b)=i∑(f(xi)−yi)2
有时候为了后续计算方便,前面也会加1/2n这样的项,求偏导
▽
w
L
(
w
,
b
)
=
2
(
w
∑
i
x
i
2
−
∑
i
(
y
i
−
b
)
x
i
)
\bigtriangledown _{w}L(w,b)=2(w\sum_{i}^{}x_{i}^{2}-\sum_{i}^{} (y_{i}-b)x_{i})
▽wL(w,b)=2(wi∑xi2−i∑(yi−b)xi)
▽
b
L
(
w
,
b
)
=
2
(
n
b
−
∑
i
(
y
i
−
w
x
i
)
)
\bigtriangledown _{b}L(w,b)=2(nb-\sum_{i}^{} (y_{i}-wx_{i}))
▽bL(w,b)=2(nb−i∑(yi−wxi))
上面=0,最优解
w
=
∑
i
y
i
(
x
i
−
1
m
∑
i
x
i
)
∑
i
x
i
2
−
1
m
(
∑
i
x
i
)
2
w=\frac{\sum_{i}^{}y_{i }(x_{i}-\frac{1}{m}\sum_{i}^{}x_{i}^{} ) }{\sum_{i}^{}x_{i}^{2} -\frac{1}{m}(\sum_{i}^{}x_{i}^{})^{2} }
w=∑ixi2−m1(∑ixi)2∑iyi(xi−m1∑ixi)
b
=
1
m
(
∑
i
y
i
−
w
x
i
)
b=\frac{1}{m}(\sum_{i}^{}y_{i}-wx_{i})
b=m1(i∑yi−wxi)
多元线性回归涉及矩阵运算,思路还是一样的,后面再写吧
三、代码
在实际应用中,很难实现一个具有 100% 准确率的感知机模型,尤其是在真实世界的数据集上。原因在于数据本身可能包含噪声、不平衡、非线性分布等问题,使得模型不可能完美分类所有样本。
感知机,二分类
//这个是gpt的
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import Perceptron
from sklearn.metrics import accuracy_score, classification_report
# 生成二分类数据集
X, y = make_classification(n_samples=1000, n_features=20, n_informative=2,
n_redundant=10, n_classes=2, random_state=42)
//1000 个样本、20 个特征的二分类数据集,其中 n_informative=2 表示有 2 个特征是真正有用的,n_redundant=10 表示有 10 个特征是冗余的。
# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
# 数据标准化
scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)
X_test = scaler.transform(X_test)
# 创建感知机模型
model = Perceptron(max_iter=1000, tol=1e-3, random_state=42)
# 训练模型
model.fit(X_train, y_train)
# 进行预测
y_pred = model.predict(X_test)
# 计算准确率
accuracy = accuracy_score(y_test, y_pred)
print(f"Accuracy: {accuracy:.2f}")
# 输出详细分类报告
print(classification_report(y_test, y_pred))
# 输出预测结果(部分)
for i in range(10): # 仅输出前 10 个样本的预测结果
print(f"Sample {i}: True label: {y_test[i]}, Predicted label: {y_pred[i]}")
//输出
Accuracy: 0.79
precision recall f1-score support
0 0.86 0.74 0.79 162
1 0.74 0.86 0.79 138
accuracy 0.79 300
macro avg 0.80 0.80 0.79 300
weighted avg 0.80 0.79 0.79 300
Sample 0: True label: 0, Predicted label: 0
Sample 1: True label: 0, Predicted label: 1
Sample 2: True label: 1, Predicted label: 1
Sample 3: True label: 0, Predicted label: 0
Sample 4: True label: 1, Predicted label: 1
Sample 5: True label: 0, Predicted label: 0
Sample 6: True label: 0, Predicted label: 0
Sample 7: True label: 0, Predicted label: 1
Sample 8: True label: 0, Predicted label: 0
Sample 9: True label: 1, Predicted label: 1
//通义灵码的
//这个更新参数的时候,是用这一步参数的模型输出和实际的y值的差作为更新量(target),这个地方的设置就是看对应的损失函数怎么设置
import numpy as np
from sklearn.metrics import accuracy_score
class Perceptron:
def __init__(self, learning_rate=0.01, n_iters=1000):
self.lr = learning_rate
self.n_iters = n_iters
self.activation_func = lambda x: 1 if x >= 0 else 0
self.weights = None
self.bias = None
def fit(self, X, y):
n_samples, n_features = X.shape
# 初始化权重和偏置
self.weights = np.zeros(n_features)
self.bias = 0
y_ = np.where(y <= 0, -1, 1) # 将标签转换为-1和1
for _ in range(self.n_iters):
for idx, x_i in enumerate(X):
linear_output = np.dot(x_i, self.weights) + self.bias
y_predicted = self.activation_func(linear_output)
update = self.lr * (y_[idx] - y_predicted)
self.weights += update * x_i
self.bias += update
def predict(self, X):
linear_output = np.dot(X, self.weights) + self.bias
y_predicted = np.vectorize(self.activation_func)(linear_output)
return y_predicted
# 生成模拟数据
np.random.seed(0)
X = np.random.rand(100, 2) * 2 - 1 # 生成范围在[-1, 1]内的随机数
y = (X[:, 0] + X[:, 1] > 0).astype(int) # 根据条件生成标签
# 划分训练集和测试集
X_train, X_test = X[:80], X[80:]
y_train, y_test = y[:80], y[80:]
# 创建并训练感知机
perceptron = Perceptron(learning_rate=0.1, n_iters=1000)
perceptron.fit(X_train, y_train)
# 预测
predictions = perceptron.predict(X_test)
# 打印预测结果
print("Predictions:", predictions)
# 计算准确率
accuracy = accuracy_score(y_test, predictions)
print(f"Accuracy: {accuracy}")
//输出’
Predictions: [0 1 1 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0]
Accuracy: 0.7
后续
回归模型其实就是计算了,等多元搞了再代码