整个项目的最终目标是要通过公司名称和其他特征,来对公司来进行行业分类;
目前大致的思路是:
1、对公司名称进行处理:包括提取关键字、通过名称来找公司之间的相似
2、引入其他特征,来对公司进行分类问题;
这里会记录我处理的整个过程
Day1
整体思路在思考,如果才能从公司名称提取到关键字,思考之后大致的思路是:
1、通过对公司名称分词之后,对每个词进行计算词频,来一个建立企业名称相关词频库;
2、定义一个阈值,将高于阈值的词作为停用词表;
3、对公司名称进行分词后,历遍停用词表,将频率高的词过滤替换;
4、最后剩下词为公司名称里频率最低的关键词
Day2
因为最后目标是要对公司进行归一化,所以主要不需要只剩关键字,将思路改成:
1、不对公司名称分词完的结果进行过滤;
2、采用信息熵的值,来对分词按熵值进行排序;
3、最后将公司分词的结果,转换成计算两个公司分词组成的两个点的距离;
Day3
按以上思路,从GP数据库中提取出11万左右的公司名称,进行建立总分词结果,以及各词的熵值;
取近1万的公司名称进行计算试运行;
#write by xyz
#-*- coding:utf-8 -*-
import pandas as pd
import numpy as np
import sklearn as sk
import time
import collections
import json
from scipy.spatial.distance import pdist
import jieba.analyse
import sys
reload(sys)
sys.setdefaultencoding('utf-8')
def word_cut_count(content,stop_words):
import collections
words_count = collections.defaultdict(lambda: 0)
company_key_word=[]
for w in content:
text = jieba.lcut(w, cut_all=False)
key_word=[]
# print text
for word in text:
if word not in stop_words and word != ' ':
words_count[word] += 1
key_word.append(word)
company_key_word.append(key_word)
return words_count,company_key_word
def word_freq(content,stop_words):
import collections
words_count,company_key_word=word_cut_count(content,stop_words)
new_words={}
count=float(sum(words_count.values()))
for key,value in words_count.items():
v = -np.log(value/count)
new_words[key]=v
new_words = collections.OrderedDict(sorted(new_words.items(), key=lambda x: x[1], reverse=True))
return new_words,new_words.keys(),new_words.values()
总共得到8万左右词的熵值
两两公司分词后的词进行合并去重,在对应的词上采用熵值作为维度坐标,转为词向量,计算向量之间的夹角cos,并计算相似度;
def company_key(company_key_word,word_freq):
company_key =[]
for i in company_key_word:
word_k={}
for j in i :
word_k[j] = float(word_freq[word_freq['word']== j]['freq'].values)
words_k = collections.OrderedDict(sorted(word_k.items(), key=lambda x: x[1], reverse=True))
company_key.append(words_k)
return company_key
def distinct(origin,obj_distinct):
'''将obj_distinct中与origin相同内容去除'''
t = []
for x in obj_distinct:
if x not in origin:
t.append(x)
return t
def word_vec(key_sum,key,entropy):
'''生成词向量'''
shape=len(key_sum)
vec = np.zeros(shape)
# print v1
for index in range(shape):
if key_sum[index] in key:
vec[index] = entropy[key_sum[index]]
return vec
result = pd.DataFrame(columns=('company_name', 'company_name_similar', 'similar_point'))
for index in range(new_data.shape[0]):
entropy = new_data.loc[index,'entropy']
key=entropy.keys()
for index1 in range(new_data.shape[0]):
if index1 != index:
entropy_p = new_data.loc[index1, 'entropy']
key_p=entropy_p.keys()
key_d = distinct(key,key_p)
key_sum = key+key_d
v1=word_vec(key_sum,key,entropy)
v2=word_vec(key_sum,key_p,entropy_p)
#计算词向量之间相似度
vv = np.vstack([v1,v2])
p1 = float(1 - pdist(vv, 'cosine')) #cos夹角相似度
# p1 = float(pdist(vv,'jaccard')) #默认欧式距离
# p1 = np.corrcoef(vv)[0][1]
if p1>0.5:
content={'company_name':new_data.loc[index,'company_name'],
'company_name_similar':new_data.loc[index1,'company_name'],
'cos_p':float(p1)}
print json.dumps((new_data.loc[index,'company_name'],new_data.loc[index1,'company_name'],p1)).decode("unicode-escape")
各公司分词后得到各词的熵值,并按熵值的value进行排序;
结果:因为熵值较低,导致量向量减仅有一个词(如‘有限公司’)相同,计算出来的相似度都高于90%;
对熵值进行调整,直接采用频率值,为了减小频率差距,对频率采取加log底,平缓频率幅度;计算出来的结果为:
到这里发现了几个问题:
1.相似度高的公司,可以看出来,基本还是可以认为结果是可以的,但是相似度较低的公司,可以发现,其实两个公司没有任何联系,只是在数字上恰好频率相同,如:
2.这里两两去比较计算,非常消耗资源,且两两会重复进行计算,最后只是通过数字进行计算,并没有从字来先判断,进行筛选;
Day4
加入筛选过程,引入树(字典);
从频率值高到低进行筛选,并且进行分类叶子节点,存储方式为字典的形式;