【机器学习】1——线性模型、感知机

机器学习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)=xiMyi(wxi+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 yiwTxi+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)=xiMyi(wxi+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)=xiMyixi
▽ b L ( w , b ) = − ∑ x i ∈ M y i \bigtriangledown _{b}L(w,b)=-\sum_{x_{i}\in M }^{} y_{i} bL(w,b)=xiMyi
然后更新参数,参数在算法开始会设定初始值,一般为0
这里随机梯度下降不用每次都用所有数据更新参数,随机选一个就可以,这样更快
w n e w ⟶ w o l d + η y i x i w_{new} \longrightarrow w_{old}+\eta y_{i}x_{i} wnewwold+ηyixi
b n e w ⟶ b o l d + η y i b_{new} \longrightarrow b_{old}+\eta y_{i} bnewbold+η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(wixi2i(yib)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(nbi(yiwxi))
上面=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=ixi2m1(ixi)2iyi(xim1ixi)
b = 1 m ( ∑ i y i − w x i ) b=\frac{1}{m}(\sum_{i}^{}y_{i}-wx_{i}) b=m1(iyiwxi)

多元线性回归涉及矩阵运算,思路还是一样的,后面再写吧


三、代码

在实际应用中,很难实现一个具有 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

后续

回归模型其实就是计算了,等多元搞了再代码

  • 29
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值