【Python】 剪辑法欠采样 CNN压缩近邻法欠采样

借鉴:关于K近邻(KNN),看这一篇就够了!算法原理,kd树,球树,KNN解决样本不平衡,剪辑法,压缩近邻法 - 知乎

但是不要看他里面的代码,因为作者把代码里的一些符号故意颠倒了 ,比如“==”改成“!=”,还有乱加“~”,看明白逻辑才能给他改过来

一、剪辑法

        当训练集数据中存在一部分不同类别数据的重叠时(在一部分程度上说明这部分数据的类别比较模糊),这部分数据会对模型造成一定的过拟合,那么一个简单的想法就是将这部分数据直接剔除掉即可,也就是剪辑法。

        剪辑法将训练集 D 随机分成两个部分,一部分作为新的训练集 Dtrain,一部分作为测试集 Dtest,然后基于 Dtrain,使用 KNN 的方法对 Dtest 进行分类,并将其中分类错误的样本从整体训练集 D 中剔除掉,得到 Dnew。

        由于对训练集 D 的划分是随机划分,难以保证数据重叠部分的样本在第一次剪辑时就被剔除,因此在得到 Dnew 后,可以对 Dnew 继续进行上述操作数次,这样可以得到一个比较清爽的类别分界。

        效果如下图:

        附上可直接运行的代码:

from sklearn import datasets
import matplotlib.pyplot as pyplot
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsClassifier as KNN
import numpy as np
from collections import Counter
from numpy import where

# make_classification用于手动构造数据
# 1000个样本,分成4类
X, y = datasets.make_classification(n_samples=1000, n_features=2,
                                            n_informative=2, n_redundant=0, n_repeated=0,
                                            n_classes=4, n_clusters_per_class=1)

# # # 画出二维散点图
# for label, _ in counter.items():
# 	row_ix = where(y == label)[0]
# 	pyplot.scatter(X[row_ix, 0], X[row_ix, 1], label=str(label))
# pyplot.legend()
# pyplot.show()

# 剪辑10次
for i in range(10):
    x_train, x_test, y_train, y_test = train_test_split(X, y, test_size=0.5)

    k = 5
    KNN_clf = KNN(n_neighbors=k)
    KNN_clf.fit(x_train, y_train)  # 用训练集训练KNN
    y_predict = KNN_clf.predict(x_test)  # 用测试集测试

    cond = y_predict == y_test
    x_test = x_test[cond]  # 把预测错误的从整体数据集中剔除掉
    y_test = y_test[cond]  # 把预测错误的从整体数据集中剔除掉

    X = np.vstack([x_train, x_test])  # 为下一次循环做准备(剔除掉本轮预测错误的
    y = np.hstack([y_train, y_test])  # 为下一次循环做准备(剔除掉本轮预测错误的

# summarize the new class distribution
counter = Counter(y)
print(counter)

# 画出二维散点图
for label, _ in counter.items():
	row_ix = where(y == label)[0]
	pyplot.scatter(X[row_ix, 0], X[row_ix, 1], label=str(label))
pyplot.legend()
pyplot.show()

        以上使用了k=20的参数进行剪辑的结果,循环了10次,一般而言,k越大,被抛弃的样本会越多,因为被分类的错误的概率更大。

二、CNN压缩近邻法欠采样

        

        压缩近邻法的想法是认为同一类型的样本大量集中在类簇的中心,而这些集中在中心的样本对分类没有起到太大的作用,因此可以舍弃掉这些样本。

        其做法是将训练集随机分为两个部分,第一个部分为 store,占所有样本的 10% 左右,第二个部分为 grabbag,占所有样本的 90% 左右,然后将 store 作为训练集训练 KNN 模型,grabbag 作为测试集,将分类错误的样本从 grabbag 中移动到 store 里,然后继续用增加了样本的 store 和减少了样本的 grabbag 再次训练和测试 KNN 模型,直到 grabbag 中所有样本被分类正确,或者 grabbag 中样本数为0。

        在压缩结束之后,store 中存储的是初始化时随机选择的 10% 左右的样本,以及在之后每一次循环中被分类错误的样本,这些被分类错误的样本集中在类簇的边缘,认为是对分类作用较大的样本。

        CNN欠采样已经有相应的Python实现库了,相应的方法是CondensedNearestNeighbour(),下面是可直接运行的代码。

# Undersample and plot imbalanced dataset with the Condensed Nearest Neighbor Rule
from collections import Counter
from sklearn.datasets import make_classification
from imblearn.under_sampling import CondensedNearestNeighbour
from matplotlib import pyplot
from numpy import where

# make_classification方法用于生成分类任务的人造数据集
# X是数据,几维都可以,n_features=4表示4维
# y用0/1表示类别,weights调整0和1的占比
X, y = make_classification(n_samples=500, n_classes=2, n_features=3, n_redundant=0,
	# n_clusters_per_class表示每个类别多少簇  # flip_y噪声,增加分类难度
	n_clusters_per_class=2, weights=[0.5], flip_y=0, random_state=1)

# summarize class distribution
counter = Counter(y)  # {0: 990, 1: 10} counter是一个字典,value存储类别,key存储类别个数
print(counter)

# ==================CNN有直接可以调用的包  n_neighbors设置k值,k值越小越省时间,就设置为1吧
undersample = CondensedNearestNeighbour(n_neighbors=1)
# transform the dataset
X, y = undersample.fit_resample(X, y)

# summarize the new class distribution
counter = Counter(y)
print(counter)

# scatter plot of examples by class label
for label, _ in counter.items():
	row_ix = where(y == label)[0]
	pyplot.scatter(X[row_ix, 0], X[row_ix, 1], label=str(label))
pyplot.legend()
pyplot.show()

        但是我觉得这个CondensedNearestNeighbour()方法的可操作性太低,所以没用这个方法,而是根据CNN的原理(CNN底层是训练KNN)去写的

from sklearn import datasets
import matplotlib.pyplot as pyplot
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsClassifier as KNN
import numpy as np
from collections import Counter
from numpy import where

# make_classification用于手动构造数据
# 1000个样本,分成4类
X, y = datasets.make_classification(n_samples=1000, n_features=2,
                                            n_informative=2, n_redundant=0, n_repeated=0,
                                            n_classes=4, n_clusters_per_class=1, random_state=1)
counter = Counter(y)
# 画出二维散点图
for label, _ in counter.items():
	row_ix = where(y == label)[0]
	pyplot.scatter(X[row_ix, 0], X[row_ix, 1], label=str(label))
pyplot.legend()
pyplot.show()

# 10%作为训练集,90%作为测试集
x_train, x_test, y_train, y_test = train_test_split(X, y, test_size=0.9)


while True:
	k = 1
	KNN_clf = KNN(n_neighbors=k)
	KNN_clf.fit(x_train, y_train)
	y_predict = KNN_clf.predict(x_test)

	cond = y_predict == y_test  # cond记录分类的对与错,分类错是False,正确是True
	# 都分类正确,退出
	if  cond.all():
		print('所有测试集都分类正确,CNN正常结束')
		break

	x_train = np.vstack([x_train, x_test[~cond]])  # 把分类错误(cond的值是False)的移动到训练集里
	y_train = np.hstack([y_train, y_test[~cond]])
	x_test = x_test[cond]  # 把分类对的继续作为下一轮的测试集
	y_test = y_test[cond]

	if len(x_test) == 0:
		print("所有样本都能做到分类错误,也就是结果集=原始数据集,一般不会出现这种情况")
		break


# summarize the new class distribution
counter = Counter(y_train)
print(counter)

# 画出二维散点图
for label, _ in counter.items():
	row_ix = where(y_train == label)[0]
	pyplot.scatter(x_train[row_ix, 0], x_train[row_ix, 1], label=str(label))
pyplot.legend()
pyplot.show()

2.1 改进版——指定压缩后样本大小的CNN

在如下代码中,用sampleNum指定全体样本数量,用endNum指定压缩后样本数量

from sklearn import datasets
import matplotlib.pyplot as pyplot
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsClassifier as KNN
import numpy as np
from collections import Counter
from numpy import where


sampleNum = 1000
endNum = 500
k = 1  # KNN算法的K值
# make_classification用于手动构造数据
# 1000个样本,分成4类
X, y = datasets.make_classification(n_samples=sampleNum, n_features=2,
                                            n_informative=2, n_redundant=0, n_repeated=0,
                                            n_classes=4, n_clusters_per_class=1, random_state=1)
# counter = Counter(y)
# # 画出二维散点图
# for label, _ in counter.items():
# 	row_ix = where(y == label)[0]
# 	pyplot.scatter(X[row_ix, 0], X[row_ix, 1], label=str(label))
# pyplot.legend()
# pyplot.show()

# 10%作为训练集,90%作为测试集
x_train, x_test, y_train, y_test = train_test_split(X, y, test_size=0.9)
# print(x_train.shape[0])  # 100

nowNum = x_train.shape[0]  # 用来控制 训练集/筛选后的样本数 满足resultNum就停下, 初始有x_train这么多个

while True:
	KNN_clf = KNN(n_neighbors=k)
	KNN_clf.fit(x_train, y_train)
	y_predict = KNN_clf.predict(x_test)
	cond = y_predict == y_test  # cond记录分类的对与错,分类错是False,正确是True
	# 都分类正确,退出
	if cond.all():
		print('所有测试集都分类正确,CNN自动结束,但是结果集没凑够呢!')
		break

	# 如果结果集数量不够要求的endNum,继续下一轮
	if nowNum+y_test[~cond].shape[0] < endNum:
		nowNum = nowNum+y_test[~cond].shape[0]
		print("目前结果集数量:", nowNum)
		x_train = np.vstack([x_train, x_test[~cond]])  # 把分类错误(cond的值是False)的移动到训练集里
		y_train = np.hstack([y_train, y_test[~cond]])
		x_test = x_test[cond]  # 把分类对的继续作为下一轮的测试集
		y_test = y_test[cond]
	# 如果结果集数量超过endNum,我们只要测试集里分类错误的前endNum-nowNum个
	else:
		# 记录前endNum-nowNum个的位置(截取位置
		condCut = 0  # 记录截取位置
		for i in range(cond.shape[0]):
			if not cond[i]:
				nowNum = nowNum + 1
			if nowNum == endNum:
				condCut = i  # 在cond[condCut]处刚好是我们要的第endNum个结果集样本
				break
		# 把cond[condCut]后面的都设置成True
		cond[condCut+1:] = True
		x_train = np.vstack([x_train, x_test[~cond]])  # 把分类错误(cond的值是False)的移动到训练集里
		y_train = np.hstack([y_train, y_test[~cond]])
		print("结果集的数量为", x_train.shape[0], "满足endNum=", endNum)
		break

	if len(x_test) == 0:
		print("所有样本都能做到分类错误,也就是结果集=原始数据集,一般不会出现这种情况")
		break


# summarize the new class distribution
counter = Counter(y_train)
print(counter)

# 画出二维散点图
for label, _ in counter.items():
	row_ix = where(y_train == label)[0]
	pyplot.scatter(x_train[row_ix, 0], x_train[row_ix, 1], label=str(label))
pyplot.legend()
pyplot.show()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/399536.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

QEMU源码全解析 —— virtio(20)

接前一篇文章&#xff1a; 上回书重点解析了virtio_pci_modern_probe函数。再来回顾一下其中相关的数据结构&#xff1a; struct virtio_pci_device struct virtio_pci_device的定义在Linux内核源码/drivers/virtio/virtio_pci_common.h中&#xff0c;如下&#xff1a; /* O…

话说激励广告

一、导言 如果一个入场口令是请问效率秘诀是&#xff1a; _ _ _&#xff0c;_ _ _ _。&#xff0c;然后她会告诉你通过小程序&#xff1a; 点“试彩蛋”&#xff0c;看完视频广告之后可以得到答案&#xff0c;这种形式是不是有点意思。这就是激励广告的一种应用场景。 激励…

[ai笔记8] 聊聊openAI最新文生视频产品-Sora

欢迎来到文思源想的ai空间&#xff0c;这是技术老兵重学ai以及成长思考的第8篇分享&#xff01; 近期sora在科技届引发不小的轰动&#xff0c;虽然这是openai并未对外发布的相关产品&#xff0c;目前如同小米汽车的技术发布会&#xff0c;但是确实引发了不小的震撼&#xff0c…

Trie树应用(最大异或对)C++(Acwing)

代码&#xff1a; #include <iostream> #include <algorithm>using namespace std;const int N 100010, M 3100010;int n; int a[N], son[M][2], idx;void insert(int x) {int p 0;for (int i 30; i > 0; i -- ){int &s son[p][x >> i & 1]…

Java+SpringBoot:滑雪场管理的技术革新

✍✍计算机编程指导师 ⭐⭐个人介绍&#xff1a;自己非常喜欢研究技术问题&#xff01;专业做Java、Python、微信小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。 ⛽⛽实战项目&#xff1a;有源码或者技术上的问题欢迎在评论区一起讨论交流&#xff01; ⚡⚡ Java实战 |…

【视频编解码】M-JPEG压缩、H.264压缩 对比

简介 参考这篇文章&#xff1a;https://blog.csdn.net/qq_41248872/article/details/83590337 写的比较好&#xff0c;这里就不赘述了。 我们在视频传输的时候&#xff0c;需要压缩&#xff0c;常见的压缩包括: jpeg 压缩h264 压缩 当然使用最多的还是 264, 毕竟他的压缩比…

我国无水氢氟酸产量逐渐增长 东岳集团市场占比较大

我国无水氢氟酸产量逐渐增长 东岳集团市场占比较大 无水氢氟酸是一种十分重要的化工产品&#xff0c;在常温常压下多表现为一种无色发烟液体。无水氢氟酸具有吸水性强、化学活性高、介电常数高、阻燃性能好等优点。经过多年发展&#xff0c;无水氢氟酸制备方法已经成熟&#xf…

【C++】 类与对象——流操作符重载,const成员函数

类与对象 流操作符重载1 << 重载2 >> 重载 const 修饰Thanks♪(&#xff65;ω&#xff65;)&#xff89;谢谢阅读&#xff01;&#xff01;&#xff01;下一篇文章见&#xff01;&#xff01;&#xff01; 流操作符重载 流操作符功能<<输出操作符>>输…

小程序--模板语法

一、插值{{}}语法 1、内容绑定 <view>{{iptValue}}</view> 2、属性绑定 <switch checked"{{true}}" /> Page({data: {iptValue: 123} }) 二、简易双向数据绑定 model:value&#xff1a;支持双向数据绑定 注&#xff1a;仅input和textarea支持&a…

QT编写工具基本流程(自用)

以后有人让你写工具的时候&#xff0c;可以方便用这个模版及时提高工作效率&#xff0c;可以争取早点下班。包含库目录&#xff0c;头文件目录&#xff0c;输出目录以及翻译和部署&#xff0c;基本上都全了&#xff0c;也可以做收藏用用。 文章目录 1、创建项目Dialog Widget都…

SpringBoot + Nacos + K8s 优雅停机

1 概念 2 用案例说话 案例前&#xff1a;k8s 停机流程 k8s springboot nacos 案例 案例优化 3 再次优化 mq 和 定时任务 流量控制 4 小结 1 概念 优雅停机是什么&#xff1f;网上说的优雅下线、无损下线&#xff0c;都是一个意思。 优雅停机&#xff0c;通常是指在设…

推荐“应用随机过程”学习材料

今天在检索资料的时候&#xff0c;无意间发现了这份由李东风老师的“应用随机过程 (pku.edu.cn)”。

LeetCode.105. 从前序与中序遍历序列构造二叉树

题目 105. 从前序与中序遍历序列构造二叉树 分析 这道题是告诉我们一颗二叉树的前序和中序&#xff0c;让我们根据前序和中序构造出整颗二叉树。 拿到这道题&#xff0c;我们首先要知道前序的中序又怎样的性质&#xff1a; 前序&#xff1a;【根 左 右】中序&#xff1a;…

LeetCode 450.删除二叉搜索树中的节点和669.修建二叉搜索树思路对比 及heap-use-after-free问题解决

题目描述 450.删除二叉搜索树中的节点 给定一个二叉搜索树的根节点 root 和一个值 key&#xff0c;删除二叉搜索树中的 key 对应的节点&#xff0c;并保证二叉搜索树的性质不变。返回二叉搜索树&#xff08;有可能被更新&#xff09;的根节点的引用。 一般来说&#xff0c;…

Python从进阶到高级—通俗易懂版

Python从进阶到高级—通俗易懂版 一、简介 Python 进阶是我一直很想写的&#xff0c;作为自己学习的记录&#xff0c;过去自己在看一些代码的时候经常会困惑&#xff0c;看不懂&#xff0c;然后自己去查资料、看书籍&#xff0c;慢慢的一个个弄懂&#xff0c;经常沉浸其中。关…

Spring Boot项目中TaskDecorator的应用实践

一、前言 TaskDecorator是一个执行回调方法的装饰器&#xff0c;主要应用于传递上下文&#xff0c;或者提供任务的监控/统计信息&#xff0c;可以用于处理子线程与主线程间数据传递的问题。 二、开发示例 1.自定义TaskDecorator import org.springframework.core.task.Task…

算法沉淀——穷举、暴搜、深搜、回溯、剪枝综合练习一(leetcode真题剖析)

算法沉淀——穷举、暴搜、深搜、回溯、剪枝综合练习一 01.全排列02.子集03.找出所有子集的异或总和再求和04.全排列 II05.电话号码的字母组合 01.全排列 题目链接&#xff1a;https://leetcode.cn/problems/permutations/ 给定一个不含重复数字的数组 nums &#xff0c;返回其…

BioTech - 大型蛋白质复合物的组装流程 (CombFold)

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://spike.blog.csdn.net/article/details/136187314 CombFold是用于预测大型蛋白质复合物结构的组合和分层组装算法&#xff0c;利用AlphaFold2预测的亚基之间的成对相互作用。CombFold的组…

C++学习:总结

#include <bits/stdc.h> using namespace std; int main() {int n;cin >> n;int a[n];for(int i0 ; i < n ;i ){cin >> a[i];}sort(a,a n);for(int i 0;i< n;i){cout << a[i] << " ";}cout << endl;// 请在此输入您的代…

IDEA查询对应功能的快捷键

首先要知道快捷键的key叫什么&#xff0c;然后通过key来找到对应的快捷键 比如下面这个查找删除导入未使用的类 跳转 或者安装对应插件