白板推导系列Pytorch-高斯判别分析(GDA)

白板推导系列Pytorch-高斯判别分析(GDA)

不同于感知机和逻辑回归中由于得到的参数方程无法直接求解而只能采用随机梯度下降或上升的方式来求极值,LDA和GDA都可以直接求得参数,因而不需要通过逐步训练

导入需要的包

import torch
import matplotlib.pyplot as plt
import numpy as np

生成数据集

def create_dataset(n_samples=1000):
    n_data = torch.ones(n_samples//2, 2)
    x0 = torch.normal(2 * n_data, 1)  # 生成均值为2.标准差为1的随机数组成的矩阵 shape=(100, 2)
    y0 = torch.zeros(n_samples//2)
    x1 = torch.normal(-2 * n_data, 1)  # 生成均值为-2.标准差为1的随机数组成的矩阵 shape=(100, 2)
    y1 = torch.ones(n_samples//2)

    #合并数据x,y
    x=torch.cat((x0,x1),0).type(torch.FloatTensor)
    y=torch.cat((y0,y1),0).type(torch.FloatTensor)
    return x,y

定义高斯函数

def Gauss(x,miu,sigma):
    x_diff = (x-miu).view(sigma.shape[0],-1)
    sigma_inv = torch.inverse(sigma+torch.eye(sigma.shape[0])*0.001)
    sigma_det = torch.det(sigma+torch.eye(sigma.shape[0])*0.001)
    a = 1/(np.power(2*np.pi,sigma.shape[0]/2)*np.sqrt(sigma_det))
    return a*torch.exp(-0.5*torch.chain_matmul(x_diff.T,sigma_inv,x_diff))

定义模型

class GDA:
    def __init__(self) -> None:
        pass

    def fit(self,X_data,y_data):
        # 我们需要在fit函数中利用数据求得四个参数
        # 首先,求 fi
        self.fi = y_data.sum()/len(y_data)
        
        # 其次,求u0,u1
        self.u1 = torch.zeros(size=(X_data.shape[1],),dtype=torch.float)
        self.u0 = torch.zeros(size=(X_data.shape[1],),dtype=torch.float)
        for i in range(X_data.shape[0]):
            self.u1 += X_data[i]*y_data[i]
            self.u0 += X_data[i]*(1-y_data[i])
        self.u1 = self.u1/y_data.sum()
        self.u0 = self.u0/(len(y_data)-y_data.sum())

        # 再次,求Sigma,但在求Sigma之前需要先求得正负样本的协方差
        self.s1 = torch.zeros(size=(X_data.shape[1],X_data.shape[1]),dtype=torch.float)
        self.s0 = torch.zeros(size=(X_data.shape[1],X_data.shape[1]),dtype=torch.float)

        for i in range(X_data.shape[0]):
            x1_diff = (X_data[i]-self.u1).view(self.u1.shape[0],-1)
            x0_diff = (X_data[i]-self.u0).view(self.u0.shape[0],-1)
            self.s1 += y[i]*torch.matmul(x1_diff,x1_diff.T)
            self.s0 += (1-y[i])*torch.matmul(x0_diff,x0_diff.T)
        
        # 注意,前面求得的s1,s0都已经乘上了各自的样本数,所以后面求sigma的时候直接相加即可
        # 最后求得sigma
        self.sigma = (self.s1+self.s0)/X_data.shape[0]
    
    def predict(self,X_data):
        pred = []
        for x in X_data:
            pred1 = Gauss(x,self.u1,self.sigma)*self.fi
            pred0 = Gauss(x,self.u0,self.sigma)*(1-self.fi)
            if pred1>pred0:
                pred.append(1)
            else:
                pred.append(0)
        return torch.tensor(pred,dtype=float)
    def score(self,X_data,y_data):
        y_pred = self.predict(X_data)
        return (y_pred==y_data).sum()/len(y_data)

测试

X,y = create_dataset(1000)
plt.scatter(X[:,0],X[:,1],c=y)
gda = GDA()
gda.fit(X[:800],y[:800])
gda.score(X[800:],y[800:])
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

孤独腹地

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值