物流地址类数据分类算法

物流地址类数据分类算法

项目情况:在工作的过程中拿到一部分物流数据,格式比较杂乱,无法区分这些地址的归属省市区信息,客户想让我把数据进行处理,最终效果为能从数据中提取出省市区信息。

现有数据有7000多条,样例数据如下。

姓名 地址
张三 株洲市XX区XX街道XX路XX小区X栋X单元XX
李四 吴兴区XX镇XX南路XX花园X撞X单元XXX
张三 山东省青岛市即墨市XX办事处北XX村
李四 河南省郑州市新郑市XX路XXXX小区
张三 江苏省扬州市邗江区XX小区北苑X栋X号
李四 广东省广州市XX区XXX
张三 广东省深圳市龙岗区XXX园

想达到效果:

姓名 地址 省份 区县
张三 株洲市芦淞区XX街道XX路XX小区X栋X单元XX 湖南 株洲 芦淞
李四 吴兴区XX镇XX南路XX花园X撞X单元XXX 浙江 湖州 吴兴
张三 山东省青岛市即墨市XX办事处北XX村 山东 青岛 即墨
李四 河南省郑州市新郑市XX路XXXX小区 河南 郑州 新郑
张三 江苏省扬州市邗江区XX小区北苑X栋X号 江苏 扬州 邗江
李四 广东省广州市天河区XXX 广东 广州 天河
张三 广东省深圳市龙岗区XXX园 广东 深圳 龙岗

给的这部分数据中一部分都是有省市区的,有5000条数据,实际上客户那里80%的数据都是没有省市区的,需要从原数据中提取。

常规机器学习算法效果不佳

​ 第一天拿到数据以后,清洗完,高高兴兴用jieba分词,将数据词组切分,提取关键词然后使用k近邻,随机森林,贝叶斯等进行机器学习算法进行分类,效果不佳。可能是数据量太小或者是类别过多,分类效果最好的是贝叶斯,但是准确率也就55%,这个准确率实在太低了,第一天就这么没了。

换个思路,为什么一定要走别人的路

​ 第二天的时候我看着那些数据,肉眼看是能够区分这些地址归属地的,而且比较有规律,比如数据中出现了某某县或者区,那我就可以根据这个县/区的名称去反推所属省份,这貌似也是个路子。依照这个思路,我就需要做出中国所有省市区的三级对应关系表,然后将原数据中的数据进行分词,和省市区的关系表进行比对,比对成功的自然就是我们想要的了。而且这个方法不用对数据进行学习,貌似也是一个非监督学习算法,编写出第一个非监督学习算法,还是很高兴的。

实现过程

想要完成这项工作,必不可少的就是需要一份中国行政区划表(全国有3000多个县级区域,也就是分类最后要有3000多类,并且区域名称和级别会随时间改变,注意更新对照表)。像这样的:

省份 区县
北京 北京市 东城区
北京 北京市 怀柔区
北京 北京市 平谷区
北京 北京市 密云县
北京 北京市 延庆县

这个表可以在中国统计局官网找到,github也有相关的爬虫项目。

有了这个表以后最终分类的结果就是“省--市--区”的结构,比如:山东省青岛市即墨市XX办事处北XX村,最后给的标签就是“山东--青岛--即墨”。

下面说实现过程:

1、分词

使用jieba分词将地址数据切分成一个个关键词,然后去重。

举个例子来说:

”上海市浦东区南京西路XX号“分词以后的结果就是('号', '区', 'XX', '浦东', '西路', '上海市', '南京')

2、创建关键词集合

创建识别每一个区域所依据的关键词组,例如“ 南京市秦淮区 ”对应的关键词组为(江苏、江苏省、南京、南京市、秦淮、秦淮区),之所以这样是因为有的人填写地址时会加省市区,而有的人不会,jieba分词的时候如果有江苏省这样的字符,分出来的是“ 江苏省 ”而不是“江苏、省”。

3、计算重合度

重合度=(待分类地址关键词与地名关键词重合数)/地名关键词个数

举个例子:

上海市浦东区这个地名的关键词就是(上海、浦东、上海市、浦东区)

南京市秦淮区的关键词就是(江苏、江苏省、南京、南京市、秦淮、秦淮区)

待分类地址 “上海市浦东区南京西路XX号” 分词以后提取的关键词为(上海市、浦东区、南京、西路、XX号)

与上海浦东重合的关键词是(上海市、浦东区),重合度就是 2/4 =0.5,

与南京重合的关键词是(南京),重合度就是1/4=0.25,

结果我们取重合度最高的,也就是“上海市浦东区”

4、代码运行流程:

待分类地址数据 ---> jieba分词 ---> 与所有区域的关键词进行比对 ---> 计算出重合度最高的一个结果返回

5、上代码

因为前面原理说的已经很清楚了,所以代码方面就不做过多解释。

import jieba
import pandas
import numpy

#文件位置
file_path=r'.\重合度计算数据.xlsx'
file_path1=r'.\地址训练用数据.xlsx'


def cut_str(string):
    #分词
    a=jieba.cut(string,cut_all=False)
    return set(a)


#设置预设关键词字典
def chd(a,b):
    dict_1={}
    count=0
    for i in a['full_name_1']:
        dict_1[count]=set(i.split('-'))
        count+=1
    return dict_1

#计算重合度最高的词组
def distance(dict_1,set_i):
    b=[]
    count=0
    for i in range(len(dict_1)):
        c=dict_1[i]&set_i
        b.append(len(c)/len(dict_1[i]))
    max_b=max(b)
    return b.index(max_b)

#读取数据
a=pandas.read_excel(file_path)
b=pandas.read_excel(file_path1)
b=b[['地址','labels']]


dict_1=chd(a,b)
predict=[]
for addr in b['地址']:
    index_max=distance(dict_1,cut_str(addr))
    predict.append(a['labels'][index_max])

'''
预测结果输出
predict_dict={'地址':list(b['地址']),'predict':predict}
out_put=pandas.DataFrame(predict_dict)
out_put.to_excel(r'.\预测结果.xlsx',index=None)
'''

#计算准确率
num=0
for k in range(len(predict)):
    if predict[k]!=b['labels'][k] :
        num+=1
        #if list(predict[k].split('-'))[:2]!=list(b['labels'][k].split('-'))[:2] :
        print(predict[k],b['labels'][k]) #输出错误预测结果

print('验证准确率:','{:%}'.format(1-num/len(predict)))

运算结果:

甘肃省-陇南市-武都区 甘肃省-陇南市-成县
甘肃省-陇南市-武都区 甘肃省-陇南市-文县
甘肃省-陇南市-武都区 甘肃省-陇南市-康县
甘肃省-陇南市-武都区 甘肃省-陇南市-礼县
新疆维吾尔自治区-和田地区-和田市 新疆维吾尔自治区-和田地区-和田县
山西省-阳泉市-城区 山西省-阳泉市-郊区
湖南省-长沙市-长沙县 湖南省-长沙市-望城区
江西省-赣州市-赣县 江西省-赣州市-龙南县
台湾-宜兰县-宜兰市 台湾-台中市-东区
台湾-台东县-关山镇 台湾-台东县-台东市
甘肃省-陇南市-武都区 甘肃省-陇南市-徽县
台湾-台东县-关山镇 台湾-台东县-台东市
验证准确率: 98.962443%

截取了最后几条结果作为展示。可以看到准确率还是很高的,将近99%,如果数据只分类到市一级的话准确率几乎达到了100%,只有极小的误差,不过现在的结果已经给客户的工作带来很大的帮助了。

其实代码还有需要优化的地方,比如说最大值选择的时候,没处理重合度相同的情况,因为之后也没再处理这方面的数据,这部分也就没再处理。

如果有人对这个感兴趣,也想拿这份数据做练习的话,可以私聊我,留下邮箱,我看到消息会回复的。

你可能感兴趣的:(物流地址类数据分类算法)