这几天在做用户画像,特征是用户的消费商品的消费金额,原始数据(部分)是这样的:

 id      goods_name goods_amount
男士手袋 1882.0
淑女装 2491.0
女士手袋 345.0
基础内衣 328.0
商务正装 4985.0
时尚 969.0
女饰品 86.0
专业运动 399.0
童装(中大童) 2033.0
男士配件 38.0

我们看到同一个id下面有不同的消费记录,这个数据不能直接拿来用,写了python程序来进行处理:test.py

 #!/usr/bin/python
#coding:utf-8
#Author:Charlotte
import pandas as pd
import numpy as np
import time #加载数据文件(你可以加载自己的文件,文件格式如上所示)
x=pd.read_table('test.txt',sep = " ") #去除NULL值
x.dropna() a1=list(x.iloc[:,0])
a2=list(x.iloc[:,1])
a3=list(x.iloc[:,2]) #A是商品类别
dicta=dict(zip(a2,zip(a1,a3)))
A=list(dicta.keys())
#B是用户id
B=list(set(a1)) # data_class = pd.DataFrame(A,lista) #创建商品类别字典
a = np.arange(len(A))
lista = list(a)
dict_class = dict(zip(A,lista))
print dict_class f=open('class.txt','w')
for k ,v in dict_class.items():
f.write(str(k)+'\t'+str(v)+'\n')
f.close() #计算运行时间
start=time.clock() #创建大字典存储数据
dictall = {}
for i in xrange(len(a1)):
if a1[i] in dictall.keys():
value = dictall[a1[i]]
j = dict_class[a2[i]]
value[j] = a3[i]
dictall[a1[i]]=value
else:
value = list(np.zeros(len(A)))
j = dict_class[a2[i]]
value[j] = a3[i]
dictall[a1[i]]=value #将字典转化为dataframe
dictall1 = pd.DataFrame(dictall)
dictall_matrix = dictall1.T
print dictall_matrix end = time.clock()
print "赋值过程运行时间是:%f s"%(end-start)

输出结果:

{'\xe4\xb8\x93\xe4\xb8\x9a\xe8\xbf\x90\xe5\x8a\xa8': 4, '\xe7\x94\xb7\xe5\xa3\xab\xe6\x89\x8b\xe8\xa2\x8b': 1, '\xe5\xa5\xb3\xe5\xa3\xab\xe6\x89\x8b\xe8\xa2\x8b': 2, '\xe7\xab\xa5\xe8\xa3\x85\xef\xbc\x88\xe4\xb8\xad\xe5\xa4\xa7\xe7\xab\xa5)': 3, '\xe7\x94\xb7\xe5\xa3\xab\xe9\x85\x8d\xe4\xbb\xb6': 9, '\xe5\x9f\xba\xe7\xa1\x80\xe5\x86\x85\xe8\xa1\xa3': 8, '\xe6\x97\xb6\xe5\xb0\x9a': 6, '\xe6\xb7\x91\xe5\xa5\xb3\xe8\xa3\x85': 7, '\xe5\x95\x86\xe5\x8a\xa1\xe6\xad\xa3\xe8\xa3\x85': 5, '\xe5\xa5\xb3\xe9\xa5\xb0\xe5\x93\x81': 0}

    0     1    2     3    4     5    6     7    8   9
1 0 1882 0 0 0 0 0 0 0 0
2 0 0 345 0 0 0 0 2491 0 0
4 0 0 0 0 0 0 0 0 328 0
5 86 0 0 0 0 4985 969 0 0 0
6 0 0 0 2033 399 0 0 0 0 38
赋值过程运行时间是:0.004497 s linux环境下字符编码不同,class.txt:
专业运动 4
男士手袋 1
女士手袋 2
童装(中大童) 3
男士配件 9
基础内衣 8
时尚 6
淑女装 7
商务正装 5
女饰品 0 得到的dicta_matrix 就是我们拿来跑数据的格式,每一列是商品名称,每一行是用户id

   现在我们来跑AE模型(Auto-encoder),简单说说AE模型,主要步骤很简单,有三层,输入-隐含-输出,把数据input进去,encode然后再decode,cost_function就是output与input之间的“差值”(有公式),差值越小,目标函数值越优。简单地说,就是你输入n维的数据,输出的还是n维的数据,有人可能会问,这有什么用呢,其实也没什么用,主要是能够把数据缩放,如果你输入的维数比较大,譬如实际的特征是几千维的,全部拿到算法里跑,效果不见得好,因为并不是所有特征都是有用的,用AE模型后,你可以压缩成m维(就是隐含层的节点数),如果输出的数据和原始数据的大小变换比例差不多,就证明这个隐含层的数据是可用的。这样看来好像和降维的思想类似,当然AE模型的用法远不止于此,具体贴一篇梁博的博文

不过梁博的博文是用c++写的,这里使用python写的代码(开源代码,有少量改动):

 #/usr/bin/python
#coding:utf-8 import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn import preprocessing class AutoEncoder():
""" Auto Encoder
layer 1 2 ... ... L-1 L
W 0 1 ... ... L-2
B 0 1 ... ... L-2
Z 0 1 ... L-3 L-2
A 0 1 ... L-3 L-2
""" def __init__(self, X, Y, nNodes):
# training samples
self.X = X
self.Y = Y
# number of samples
self.M = len(self.X)
# layers of networks
self.nLayers = len(nNodes)
# nodes at layers
self.nNodes = nNodes
# parameters of networks
self.W = list()
self.B = list()
self.dW = list()
self.dB = list()
self.A = list()
self.Z = list()
self.delta = list()
for iLayer in range(self.nLayers - 1):
self.W.append( np.random.rand(nNodes[iLayer]*nNodes[iLayer+1]).reshape(nNodes[iLayer],nNodes[iLayer+1]) )
self.B.append( np.random.rand(nNodes[iLayer+1]) )
self.dW.append( np.zeros([nNodes[iLayer], nNodes[iLayer+1]]) )
self.dB.append( np.zeros(nNodes[iLayer+1]) )
self.A.append( np.zeros(nNodes[iLayer+1]) )
self.Z.append( np.zeros(nNodes[iLayer+1]) )
self.delta.append( np.zeros(nNodes[iLayer+1]) ) # value of cost function
self.Jw = 0.0
# active function (logistic function)
self.sigmod = lambda z: 1.0 / (1.0 + np.exp(-z))
# learning rate 1.2
self.alpha = 2.5
# steps of iteration 30000
self.steps = 10000 def BackPropAlgorithm(self):
# clear values
self.Jw -= self.Jw
for iLayer in range(self.nLayers-1):
self.dW[iLayer] -= self.dW[iLayer]
self.dB[iLayer] -= self.dB[iLayer]
# propagation (iteration over M samples)
for i in range(self.M):
# Forward propagation
for iLayer in range(self.nLayers - 1):
if iLayer==0: # first layer
self.Z[iLayer] = np.dot(self.X[i], self.W[iLayer])
else:
self.Z[iLayer] = np.dot(self.A[iLayer-1], self.W[iLayer])
self.A[iLayer] = self.sigmod(self.Z[iLayer] + self.B[iLayer])
# Back propagation
for iLayer in range(self.nLayers - 1)[::-1]: # reserve
if iLayer==self.nLayers-2:# last layer
self.delta[iLayer] = -(self.X[i] - self.A[iLayer]) * (self.A[iLayer]*(1-self.A[iLayer]))
self.Jw += np.dot(self.Y[i] - self.A[iLayer], self.Y[i] - self.A[iLayer])/self.M
else:
self.delta[iLayer] = np.dot(self.W[iLayer].T, self.delta[iLayer+1]) * (self.A[iLayer]*(1-self.A[iLayer]))
# calculate dW and dB
if iLayer==0:
self.dW[iLayer] += self.X[i][:, np.newaxis] * self.delta[iLayer][:, np.newaxis].T
else:
self.dW[iLayer] += self.A[iLayer-1][:, np.newaxis] * self.delta[iLayer][:, np.newaxis].T
self.dB[iLayer] += self.delta[iLayer]
# update
for iLayer in range(self.nLayers-1):
self.W[iLayer] -= (self.alpha/self.M)*self.dW[iLayer]
self.B[iLayer] -= (self.alpha/self.M)*self.dB[iLayer] def PlainAutoEncoder(self):
for i in range(self.steps):
self.BackPropAlgorithm()
print "step:%d" % i, "Jw=%f" % self.Jw def ValidateAutoEncoder(self):
for i in range(self.M):
print self.X[i]
for iLayer in range(self.nLayers - 1):
if iLayer==0: # input layer
self.Z[iLayer] = np.dot(self.X[i], self.W[iLayer])
else:
self.Z[iLayer] = np.dot(self.A[iLayer-1], self.W[iLayer])
self.A[iLayer] = self.sigmod(self.Z[iLayer] + self.B[iLayer])
print "\t layer=%d" % iLayer, self.A[iLayer] data=[]
index=[]
f=open('./data_matrix.txt','r')
for line in f.readlines():
ss=line.replace('\n','').split('\t')
index.append(ss[0])
ss1=ss[1].split(' ')
tmp=[]
for i in xrange(len(ss1)):
tmp.append(float(ss1[i]))
data.append(tmp)
f.close() x = np.array(data)
#归一化处理
xx = preprocessing.scale(x)
nNodes = np.array([ 10, 5, 10])
ae3 = AutoEncoder(xx,xx,nNodes)
ae3.PlainAutoEncoder()
ae3.ValidateAutoEncoder() #这是个例子,输出的结果也是这个
# xx = np.array([[0,0,0,0,0,0,0,1], [0,0,0,0,0,0,1,0], [0,0,0,0,0,1,0,0], [0,0,0,0,1,0,0,0],[0,0,0,1,0,0,0,0], [0,0,1,0,0,0,0,0]])
# nNodes = np.array([ 8, 3, 8 ])
# ae2 = AutoEncoder(xx,xx,nNodes)
# ae2.PlainAutoEncoder()
# ae2.ValidateAutoEncoder()

这里我拿的例子做的结果,真实数据在服务器上跑,大家看看这道啥意思就行了

[0 0 0 0 0 0 0 1]
layer=0 [ 0.76654705 0.04221051 0.01185895]
layer=1 [ 4.67403977e-03 5.18624788e-03 2.03185410e-02 1.24383559e-02
1.54423619e-02 1.69197292e-03 2.34471751e-05 9.72956513e-01]
[0 0 0 0 0 0 0]
layer=0 [ 0.08178768 0.96348458 0.98583155]
layer=1 [ 8.18926274e-04 7.30041977e-04 1.06452565e-02 9.94423121e-03
3.47329848e-03 1.32582980e-02 9.80648863e-01 8.42319408e-08]
[0 0 0 0 0 0 0]
layer=0 [ 0.04752084 0.01144966 0.67313608]
layer=1 [ 4.38577163e-03 4.12704649e-03 1.83408905e-02 1.59209302e-05
2.32400619e-02 9.71429772e-01 1.78538577e-02 2.20897151e-03]
[0 0 0 0 0 0 0]
layer=0 [ 0.00819346 0.37410028 0.0207633 ]
layer=1 [ 8.17965283e-03 7.94760145e-03 4.59916741e-05 2.03558668e-02
9.68811657e-01 2.09241369e-02 6.19909778e-03 1.51964053e-02]
[0 0 0 0 0 0 0]
layer=0 [ 0.88632868 0.9892662 0.07575306]
layer=1 [ 1.15787916e-03 1.25924912e-03 3.72748604e-03 9.79510789e-01
1.09439392e-02 7.81892291e-08 1.06705286e-02 1.77993321e-02]
[0 0 0 0 0 0 0]
layer=0 [ 0.9862938 0.2677048 0.97331042]
layer=1 [ 6.03115828e-04 6.37411444e-04 9.75530999e-01 4.06825647e-04
2.66386294e-07 1.27802666e-02 8.66599313e-03 1.06025228e-02]

可以很明显看layer1和原始数据是对应的,所以我们可以把layer0作为降维后的新数据。

最后在进行聚类,这个就比较简单了,用sklearn的包,就几行代码:

 # !/usr/bin/python
# coding:utf-8
# Author :Charlotte from matplotlib import pyplot
import scipy as sp
import numpy as np
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
from scipy import sparse
import pandas as pd
import Pycluster as pc
from sklearn import preprocessing
from sklearn.preprocessing import StandardScaler
from sklearn import metrics
import pickle
from sklearn.externals import joblib #加载数据
data = pd.read_table('data_new.txt',header = None,sep = " ")
x = data.ix[:,1:141]
card = data.ix[:,0]
x1 = np.array(x)
xx = preprocessing.scale(x1)
num_clusters = 5 clf = KMeans(n_clusters=num_clusters, n_init=1, n_jobs = -1,verbose=1)
clf.fit(xx)
print(clf.labels_)
labels = clf.labels_
#score是轮廓系数
score = metrics.silhouette_score(xx, labels)
# clf.inertia_用来评估簇的个数是否合适,距离越小说明簇分的越好
print clf.inertia_
print score

  这个数据是拿来做例子的,维度少,效果不明显,真实环境下的数据是30W*142维的,写的mapreduce程序进行数据处理,然后通过AE模型降到50维后,两者的clf.inertia_和silhouette(轮廓系数)有显著差异:

 

clf.inertia_

silhouette

base版本

252666.064229

0.676239435

AE模型跑后的版本

662.704257502

0.962147623

所以可以看到没有用AE模型直接聚类的模型跑完后的clf.inertia_比用了AE模型之后跑完的clf.inertia_大了几个数量级,AE的效果还是很显著的。

以上是随手整理的,如有错误,欢迎指正:)

【原】KMeans与深度学习模型结合提高聚类效果的更多相关文章

  1. NeuralEnhance: 提高图像分辨率的深度学习模型

    NeuralEnhance是使用深度学习训练的提高图像分辨率的模型,使用Python开发,项目地址:https://github.com/alexjc/neural-enhance. 貌似很多电影都有 ...

  2. AI佳作解读系列(一)——深度学习模型训练痛点及解决方法

    1 模型训练基本步骤 进入了AI领域,学习了手写字识别等几个demo后,就会发现深度学习模型训练是十分关键和有挑战性的.选定了网络结构后,深度学习训练过程基本大同小异,一般分为如下几个步骤 定义算法公 ...

  3. 利用 TFLearn 快速搭建经典深度学习模型

      利用 TFLearn 快速搭建经典深度学习模型 使用 TensorFlow 一个最大的好处是可以用各种运算符(Ops)灵活构建计算图,同时可以支持自定义运算符(见本公众号早期文章<Tenso ...

  4. PyTorch如何构建深度学习模型?

    简介 每过一段时间,就会有一个深度学习库被开发,这些深度学习库往往可以改变深度学习领域的景观.Pytorch就是这样一个库. 在过去的一段时间里,我研究了Pytorch,我惊叹于它的操作简易.Pyto ...

  5. Opencv调用深度学习模型

    https://blog.csdn.net/lovelyaiq/article/details/79929393 https://blog.csdn.net/qq_29462849/article/d ...

  6. 深度学习模型调优方法(Deep Learning学习记录)

    深度学习模型的调优,首先需要对各方面进行评估,主要包括定义函数.模型在训练集和测试集拟合效果.交叉验证.激活函数和优化算法的选择等. 那如何对我们自己的模型进行判断呢?——通过模型训练跑代码,我们可以 ...

  7. CUDA上深度学习模型量化的自动化优化

    CUDA上深度学习模型量化的自动化优化 深度学习已成功应用于各种任务.在诸如自动驾驶汽车推理之类的实时场景中,模型的推理速度至关重要.网络量化是加速深度学习模型的有效方法.在量化模型中,数据和模型参数 ...

  8. CUDA上的量化深度学习模型的自动化优化

    CUDA上的量化深度学习模型的自动化优化 深度学习已成功应用于各种任务.在诸如自动驾驶汽车推理之类的实时场景中,模型的推理速度至关重要.网络量化是加速深度学习模型的有效方法.在量化模型中,数据和模型参 ...

  9. 使用 PyTorch Lightning 将深度学习管道速度提高 10 倍

    ​  前言  本文介绍了如何使用 PyTorch Lightning 构建高效且快速的深度学习管道,主要包括有为什么优化深度学习管道很重要.使用 PyTorch Lightning 加快实验周期的六种 ...

随机推荐

  1. 如何使用github搭建个人博客

    1.去github官网注册个人帐号:没有的:猛戳这里去注册,比如我的账户名:wjf444128852,我的已经汉化(可在github里搜索github如何汉化有插件) 2.点击仓库-新建,仓库名字必须 ...

  2. 原生JS实战:分享一个首页进度加载动画!

    本文是苏福的原创文章,转载请注明出处:苏福CNblog:http://www.cnblogs.com/susufufu/p/5871134.html 该程序是本人的个人作品,写的不好,可以参考,但未经 ...

  3. React Native开发入门

    目录: 一.前言 二.什么是React Native 三.开发环境搭建 四.预备知识 五.最简单的React Native小程序 六.总结 七.参考资料   一.前言 虽然只是简单的了解了一下Reac ...

  4. KEIL中启动文件详解(汇编语言)

    原文在此:http://www.cnblogs.com/mddblog/p/4920063.html 概述 在嵌入式系统中,启动文件是整个系统非常关键的部分,它会进行一些底层的初始化,构建程序运行必要 ...

  5. android 7.0 学习笔记(一)

    导读 增强的Doze模式 后台优化 Data Saver 一.增强的Doze模式 Android N对Android M引进的Doze模式进行了进一步的增强,变化体现在两个方面.一方面是降低了进入Do ...

  6. __block 和 __weak的区别

    Blocks理解: Blocks可以访问局部变量,但是不能修改 如果修改局部变量,需要加__block __block int multiplier = 7; int (^myBlock)(int) ...

  7. 可扩展的事件复用技术:epoll和kqueue

    通常来说我喜欢Linux更甚于BSD系统,但是我真的想在Linux上拥有BSD的kqueue功能. 什么是事件复用技术 假设你有一个简单的web服务器,并且那里已经打开了两个socket连接.当服务器 ...

  8. Sqlserver通过链接服务器访问Oracle的那些事儿

    前言: 1.不经历风雨,怎能见彩虹. 2.充分利用BaiDu.google等搜索引擎查找资料并整合分析! 3.世上无难事只怕有心人! 本文由来:笔者在研究SQLSERVER链接服务器到oracle并使 ...

  9. Linux如何搜索查找文件里面内容

    在Linux系统当中,如何搜.索查找文件里面的内容呢? 这个应该是系统维护.管理当中遇到最常见的需求.那么下面介绍,总结一下如何搜索.查找文件当中的内容. 搜索.查找文件当中的内容,一般最常用的是gr ...

  10. 0025 Java学习笔记-面向对象-final修饰符、不可变类

    final关键字可以用于何处 修饰类:该类不可被继承 修饰变量:该变量一经初始化就不能被重新赋值,即使该值跟初始化的值相同或者指向同一个对象,也不可以 类变量: 实例变量: 形参: 注意可以修饰形参 ...