PLA-Pocket算法实现

原理参考:PLA算法和Pocket算法原理及Python实现

代码传送门:https://github.com/taifyang/machine-learning

python实现:

import numpy as np
import random
 
#感知机模型
class Pocket:
    def __init__(self, x, y):
        self.x = x
        self.y = y
        self.w = np.zeros(x.shape[1])  #初始化权重,w1,w2均为0
        self.best_w = np.zeros(x.shape[1])  #最好
        self.b = 0
        self.best_b = 0
 
    def sign(self, w, b, x):
        y = np.dot(x, w) + b
        return int(y)

    def classify(self,w,b):
        mistakes = []
        for i in range(self.x.shape[0]):
            tmpY = self.sign(w, b, self.x[i, :])
            if tmpY * self.y[i] <= 0:  # 如果是误分类
                mistakes.append(i)
        return mistakes

    def update(self, label_i, data_i):
        tmp = label_i * data_i
        tmpw = tmp + self.w
        tmpb = self.b + label_i
        if(len(self.classify(self.best_w,self.best_b))>=(len(self.classify(tmpw,tmpb)))):
            self.best_w = tmp + self.w
            self.best_b = self.b + label_i
        self.w = tmp + self.w
        self.b = self.b + label_i
 
    def train(self,max_iters):
        iters = 0
        isFind = False
        while not isFind:
            mistakes = self.classify(self.w,self.b)
            if(len(mistakes) == 0):
                return self.best_w, self.best_b
            n = mistakes[random.randint(0,len(mistakes)-1)]
            self.update(self.y[n], self.x[n, :])
            iters += 1
            if iters == max_iters:
                isFind = True
        return self.best_w, self.best_b


if __name__ == '__main__':
    x = np.array([[3,-3],[4,-3],[1,1],[1,2]])
    y = np.array([-1, -1, 1, 1])
    myPocket_PLA = Pocket(x, y)
    w, b = myPocket_PLA.train(50)
    print('最终训练得到的w和b为:', w, b)

C++实现:

#include <iostream>
#include <vector>
#include <time.h>

//创建数据集
void  createdata(std::vector<std::vector<float>>& x, std::vector<float>& y)
{
	x = { { 3, -3 },{ 4, -3 },{ 1, 1 },{ 1, 2 } };
	y = { -1, -1, 1, 1 };
}

//感知机模型
class Pocket
{
public:
	Pocket(std::vector<std::vector<float>> x, std::vector<float> y)
	{
		m_x = x;
		m_y = y;
		m_w.resize(m_x[0].size(), 0);
		m_best_w.resize(m_x[0].size(), 0);
		m_b = 0;
		m_best_b = 0;
	}

	float sign(std::vector<float> w, float b, std::vector<float> x)
	{
		float y = b;
		for (size_t i = 0; i < w.size(); i++)
		{
			y += w[i] * x[i];
		}
		return y;
	}

	std::vector<int> classify(std::vector<float> w, float b)
	{
		std::vector<int> mistakes;
		for (size_t i = 0; i < m_x.size(); i++)
		{
			float tmp_y = sign(w, b, m_x[i]);
			if (tmp_y*m_y[i] <= 0) //如果误分类
			{
				mistakes.push_back(i);
			}
		}
		return mistakes;
	}

	void update(float label_i, std::vector<float> data_i)
	{
		std::vector<float> tmp_w(m_w.size());
		for (size_t i = 0; i < m_w.size(); i++)
		{
			tmp_w[i] += label_i * data_i[i] + m_w[i];
		}
		float tmp_b = label_i + m_b;
		if (classify(m_best_w, m_best_b).size() >= classify(tmp_w, tmp_b).size())
		{
			for (size_t i = 0; i < m_w.size(); i++)
			{
				m_best_w[i] += label_i * data_i[i] + m_w[i];
			}
			m_best_b = label_i + m_b;
		}
		for (size_t i = 0; i < m_w.size(); i++)
		{
			m_w[i] = label_i * data_i[i] + m_w[i];
		}
		m_b = label_i + m_b;
	}

	void train(int max_iters)
	{
		int iters = 0;
		bool isFind = false;
		while (!isFind)
		{
			std::vector<int> mistakes = classify(m_w, m_b);
			if (mistakes.size() == 0)
			{
				std::cout << "最终训练得到的w为:";
				for (auto i : m_w)	std::cout << i << " ";
				std::cout << "\n最终训练得到的b为:";
				std::cout << m_b << "\n";
				break;
			}
			srand((int)time(0));
			int n = mistakes[rand() % (mistakes.size())];
			update(m_y[n], m_x[n]);
			++iters;
			if (iters == max_iters)
			{
				std::cout << "最终训练得到的w为:";
				for (auto i : m_w)	std::cout << i << " ";
				std::cout << "\n最终训练得到的b为:";
				std::cout << m_b << "\n";
				bool isFind = true;
			}
		}
	}

private:
	std::vector<std::vector<float>> m_x;
	std::vector<float> m_y;
	std::vector<float> m_w;
	std::vector<float> m_best_w;
	float m_b;
	float m_best_b;
};


int main(int argc, char** argv)
{
	std::vector<std::vector<float>> x;
	std::vector<float> y;

	createdata(x, y);

	Pocket mypocket = Pocket(x, y);
	mypocket.train(50);

	system("pause");
	return EXIT_SUCCESS;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

给算法爸爸上香

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

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

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

打赏作者

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

抵扣说明:

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

余额充值