[技术博客] K-Means算法
遇到的问题
在对微软\(OCR\)的\(api\)进行测试的过程中,我发现有时候它并不能分析出一个表格的形态,也就是说不知道每个文本对应在表格中的第几行第几列。但是它可以较为准确的给出这些文本的坐标。
不过问题是,位于同一行的文本,他们的纵坐标不是完全相同的,但是在一个大致的范围内。位于同一列的坐标也是有这样的问题。比如一个两行三列的表格,得到的\(6\)个纵坐标可能是这样的:\([32, 32, 37, 68, 70, 72]\)。那么怎么才能较为准确的分辨出哪些纵坐标其实是属于同一行的呢?
开始想过排序后看相邻差的变化量,但是这个值很难确定,大了会把两行分到一行,小了会把一行划成两行,在咨询了学长以后,学长推荐了我\(K-Means\)算法,于是对这个算法进行了学习。
K-Means
\(K-Means\)算法是聚类算法中的最常用的一种,算法最大的特点是简单,好理解,运算速度快,但是只能应用于连续型的数据,并且一定要在聚类前需要手工指定要分成几类。
聚类算法完全是靠算法自己来判断各条数据之间的相似性,相似的就放在一起。非常适合于解决我遇到的问题。
算法流程
- 随机选取\(k\)个中心点
- 遍历所有数据,将每个数据划分到最近的中心点中
- 计算每个聚类的平均值,并作为新的中心点
- 重复\(2\sim 3\)步,直到这\(k\)个中心点不再变化,或迭代次数足够多
如下图所示:

图\((a)\)为初始的数据集,图\((b)\)中随机选取了\(2\)个中心点,一个标红一个标蓝。接下来把离红点近的绿点标红,把离蓝点近的绿点标蓝。计算红点的质心和蓝点的质心作为新的中心点并不断迭代,最终得到图\((f)\)。
应用K-Means解决问题
可以看出,横、纵坐标互相独立,于是把他们分开处理。相当于在一维的直线上做聚类。
以下以对纵坐标处理为例进行说明。
K值的确定
最开始时打算使用行数作为\(K\)值,但是经过实测,这样的聚类效果并不好,而且中心点难以选取。经过思考,决定把纵坐标排序以后相邻的作差。最终分为两类,一类差值表示他们是同一行之内的坐标差值,设他们的最大值为\(eps\),另一类的差值表示它们是不同行之间的坐标差值。最终认为两个坐标的差值\(\leq eps\)则表示它们属于同一行。
于是\(k\)值被设定为2。这样在只有一行或者一列的话会容易出问题,不过这种表格比较少见而且没有太大意义,所以暂不考虑(没想到咋处理)。
初始质心的选择
随机的话我担心有时候可能效果不好,于是固定为最小的差和最大的差。实测效果还行。
距离计算
因为是在一维的直线上,所以采取差的绝对值即可。
代码实现
def distEclud(a, b):
return abs(a - b)
def K_Means(arr):
K = 2
p = []
arr.sort()
N = len(arr) - 1
for i in range(0, N):
p.append(arr[i + 1] - arr[i])
p.sort()
cluster = [p[0], p[N - 1]]
pos = [1 for i in range(0, N)]
for t in range(1, 101):
for i in range(0, N):
pos[i] = 0
for j in range(1, K):
if distEclud(cluster[pos[i]], p[i]) > distEclud(cluster[j], p[i]):
pos[i] = j
num = [0 for i in range(0, K)]
cluster = [0 for i in range(0, K)]
for i in range(0, N):
num[pos[i]] += 1
cluster[pos[i]] += p[i]
for i in range(0, K):
cluster[i] /= num[i]
eps = 0
for i in range(N):
if pos[i] == pos[0]:
eps = max(eps, p[i])
cnt = 0
dic = {}
lastVal = -2147483647
for i in range(N + 1):
if arr[i] - lastVal > eps:
cnt = cnt + 1
dic[arr[i]] = cnt
lastVal = arr[i]
dic["size"] = cnt
return dic
[技术博客] K-Means算法的更多相关文章
- 技术博客(初用markdown)。
技术博客 菜鸟教程在这个网站我学到许多有趣的东西,并且弥补了我之前的一些不足之处. 以下为我学习到的内容 输出不同的三位数 以下为代码和输出结果 *** #include<stdio.h> ...
- 技术博客(初用markdown)
技术博客 菜鸟教程在这个网站我学到许多有趣的东西,并且弥补了我之前的一些不足之处. 以下为我学习到的内容. 1 如果想输出多个多位数的时候,可以尝试用多个if语句.如果需要输出3为数的时候,设置三个变 ...
- 【转】【技术博客】Spark性能优化指南——高级篇
http://mp.weixin.qq.com/s?__biz=MjM5NjQ5MTI5OA==&mid=2651745207&idx=1&sn=3d70d59cede236e ...
- [转]有哪些值得关注的技术博客(Java篇)
有哪些值得关注的技术博客(Java篇) 大部分程序员在自学的道路上不知道走了多少坑,这个视频那个网站搞得自己晕头转向.对我个人来说我平常在学习的过程中喜欢看一些教程式的博客.这些博客的特点: 1. ...
- 最值得收藏的java技术博客(Java篇)
第一个:java_my_life 作者介绍:找不到原作者信息.大概做了翻阅全部是2012年的博客. 博客主要内容:主要内容是关于Java设计模式的一些讲解和学习笔记,在相信对学习设计模式的同学帮助很大 ...
- 一文搞定scrapy爬取众多知名技术博客文章保存到本地数据库,包含:cnblog、csdn、51cto、itpub、jobbole、oschina等
本文旨在通过爬取一系列博客网站技术文章的实践,介绍一下scrapy这个python语言中强大的整站爬虫框架的使用.各位童鞋可不要用来干坏事哦,这些技术博客平台也是为了让我们大家更方便的交流.学习.提高 ...
- 个人技术博客(α)------javaweb的学习路程
该博文大致内容是学习的一个过程,心得,并不是以技术博客为主,在此说明. 关于javaweb的学习开始的时间大概是从大二下(2017年6.7月份)的暑假开始的,在学长的介绍下加入了实验室进行学习,由于是 ...
- 50家硅谷IT公司技术博客
分享一下 50 家硅谷优秀 IT 公司技术博客,从中可以了解企业文化,技术特色和设计语言,如果直接列出来很单调,加上点评,算吐槽版吧. 知名大厂 1. Facebook https://www.f ...
- UC技术博客开放通知
国内知名浏览器UC开放技术博客( http://tech.uc.cn/),技术博客所涵盖技术点有: Hadoop Linux MySQL 前端与client技术 图像处理 开发语言和框架 数据存储 数 ...
- [技术博客]使用CDN加快网站访问速度
[技术博客]使用CDN加快网站访问速度 2s : most users are willing to wait 10s : the limit for keeping the user's atten ...
随机推荐
- 专项测试-App性能分析
专项测试 app性能 Activity是Android组件中最基本也是最为常见用的四大组件(Activity,Service服务,Content Provider内容提供者,BroadcastRece ...
- 经典多级时间轮定时器(C语言版)
经典多级时间轮定时器(C语言版) 文章目录 经典多级时间轮定时器(C语言版) 1. 序言 2. 多级时间轮实现框架 2.1 多级时间轮对象 2.2 时间轮对象 2.3 定时任务对象 2.4 双向链表 ...
- CSS导航菜单(一级菜单)
index.html <div class="nav"> <ul> <li><a href="#">Java&l ...
- JS007. 深入探讨带浮点数运算丢失精度问题(二进制的浮点数存储方式)
复现与概述 当JS在进行浮点数运算时可能产生丢失精度的情况: 从肉眼可见的程度上观察,发生精度丢失的浮点数是没有规律的,但该浮点数丢失精度的问题会100%复现.经查阅,这个问题要追溯至浮点数的二进制存 ...
- redis存取数据Hash
一.概念 二.存取散列Hash值 1. 2.JSON字符串存取,没有更新值的字段资源浪费 使用散列Hash存取,可以单独到一个或多个字段: 3.hsetnx,属性不存在就新增并赋值,属性已存在啥也不干 ...
- 清除router路由后面的参数
清除router参数: 1.this.$router.push({ query: {}}) 2.var path = this.$route.path; //获取路由路径 this.$route ...
- DLL延时加载技术与资源释放
DLL延时加载技术与资源释放 0x00 前言 诸如调用非Windows的第三方库,我们或许会使用到dll文件,而这个时候原本程序运行需要相应的dll文件才能加载启动.通过DLL延时加载技术,使用延时加 ...
- python模块--collections(容器数据类型)
Counter类(dict的子类, 计数器) 方法 返回值类型 说明 __init__ Counter 传入可迭代对象, 会对对象中的值进行计数, 值为键, 计数为值 .elements() 迭代器 ...
- RIAD配置
一.RIAD 磁盘阵列介绍 二.阵列卡介绍 三.案例举例 一.RAID磁盘阵列介绍 是Redundant Array of Independent Disks的缩写,中文简称为独立冗余磁盘阵列 把 ...
- 建立 F103C8T6 HAL库 Makefile FreeRTOS 工程
F103C8T6 HAL库 Makefile FreeRTOS 工程模板 环境 该工程的开发平台为 ARM-GCC 工具链和 Make > arm-none-eabi-gcc -v gcc ve ...