Query 聚类

为了提高阅读体验,请移步到:Query 聚类

背景

搜索系统优化长尾 query。想了解一下长尾 query 长什么样?大体上都有几类?最好能归类,一类一类处理。

Query 数据源:包含“什么”,“怎么”,“如何” 关键词的 Query。

K-means

聚类概念

生活中的聚类例子:班级分组。

一个班级有 40 名学生,班主任分别让小明,小红,小强,小李将班级中学生分成两组。

小明:男生一组,女生一组。

小红:前三排一组,后三排一组。

小强:左三列一组,又三列一组。

小李:住校生一组,走读生一组。

为什么造成大家的分组不一样?是因为老师没有给明确定分组规则。

聚类是无监督学习。

无监督学习不需要标注数据。

有监督学习需要标注数据。NB,LR。

聚类:将数据划分到不同的类里,使相似(距离相近)的数据在同一类里,不相似(距离较远)的数据在不同的类里。

Demo

生成模拟数据

from sklearn.datasets import make_blobsimport matplotlib.pyplot as plt# 生成:样本数500,特征数为2,4 个中心的样本集X, y = make_blobs(n_samples=500, n_features=2, centers=4, random_state=1)plt.scatter(X[:, 0], X[:, 1], marker='o', s=8)plt.show()

X = [[-6.92324165e+00 -1.06695320e+01][-8.63062033e+00 -7.13940564e+00][-9.63048069e+00 -2.72044935e+00][-2.30647659e+00 5.30797676e+00]]

模拟的数据的分布:

聚类及可视化代码(使用 sklearn 库中的 KMeans):

from sklearn.datasets import make_blobsimport matplotlib.pyplot as pltfrom sklearn.cluster import KMeans# 生成:样本数500,特征数为2,4 个中心的样本集X, y = make_blobs(n_samples=500, n_features=2, centers=4, random_state=1)# 聚类n_clusters = 4cluster = KMeans(n_clusters=n_clusters, random_state=0).fit(X)# 可视化 -- 样本color = ["red", "pink", "orange", "gray"]y_pred = cluster.labels_for i in range(n_clusters):    plt.scatter(X[y_pred == i, 0], X[y_pred == i, 1], marker='o', s=8, c=color[i])# 可视化 -- 质心centroid = cluster.cluster_centers_plt.scatter(centroid[:,0], centroid[:,1], marker='x', s=15, c="black")plt.show()

聚类的结果:不同颜色表示不同类型

欧式距离

点 X 到点 Y 的距离。

如图:点 与点 之间的距离为:

K-Means 算法

算法描述

  1. 从数据集中随机选取 K 个样本,作为初始质心。

  1. 重新对样本划分类别:计算每个样本 ,计算它到每一个质心的距离,将其分配到距离最小质心所对应的类中。

  1. 重新计算每个质心。

  1. 当满足一定条件,如类别划分不在变化时或者达到最大迭代轮数,则终止算法,否则继续步骤 2 和 3。

例如:绿色类中点:

跟新绿色质心:

注意:此时的质心是虚拟的点(不是训练集中的样本,后续优化点)

关键点:

  • 计算样本数据与中心点的距离

  • 欧式距离:

  • 计算聚类的中心点(更新质心)

  • 均值。

  • 算法终止条件:最小化 WCSS

Kmeans 聚类代码(自己实现方便后根据业务需求优化聚类过程):

import mathfrom random import sampleclass Kmeans:    def __init__(self):        self.centorids = []        self.labels = []    # 训练    def train(self, train_data, n_clusters=10, max_iter=300):        last_wcss = 0.0        iter_count = 0        centorids = [train_data[i] for i in sample(range(len(train_data)), n_clusters)]        print("kmeans train start:", centorids)        while True:            labels = [[] for _ in range(n_clusters)]            wcss = 0            # 聚类            for x_id in range(len(train_data)):                min_distance = math.inf                for cluster_id in range(n_clusters):                    distance = self.calc_distance(train_data[x_id], centorids[cluster_id])                    if min_distance > distance:                        min_distance = distance                        cluster = cluster_id                labels[cluster].append(x_id)                wcss += min_distance            print("kmeans wcss:", wcss, iter_count)            # modify centers            for cluster_id in range(n_clusters):                centorids[cluster_id] = self.calc_centroid(train_data, labels[cluster_id])            iter_count += 1            if last_wcss == wcss or iter_count == max_iter: break            last_wcss = wcss        self.centorids = centorids        tmp = sorted([(x_id, cluster_id) for cluster_id in range(len(labels)) for x_id in labels[cluster_id]])        self.labels = [cluster_id for x_id, cluster_id in tmp]        print("kmeans train Over")    # 计算质心    def calc_centroid(self, train_data, cluster_data):        x_dimension = len(train_data[0])        centroid = [0.0] * x_dimension        for x_id in cluster_data:            for i in range(x_dimension):                centroid[i] += train_data[x_id][i]        return [item / len(cluster_data) for item in centroid]    # 计算距离    def calc_distance(self, x, y):        return math.sqrt(sum([math.pow(i - j, 2) for i, j in zip(x, y)]))                  # 测试from sklearn.datasets import make_blobsimport matplotlib.pyplot as pltimport numpy as np# 生成:样本数500,特征数为2,4 个中心的样本集X, y = make_blobs(n_samples=500, n_features=2, centers=4, random_state=1)# 聚类kmeans = Kmeans()kmeans.train(X, k=4)# 可视化color = ["red", "pink", "orange", "gray"]# 可视化 -- 样本y_pred = np.array(kmeans.labels)for i in range(n_clusters):    plt.scatter(X[y_pred == i, 0], X[y_pred == i, 1], marker='o', s=8, c=color[i])# 可视化 -- 质心centroid = np.array(kmeans.centorids)plt.scatter(centroid[:, 0], centroid[:, 1], marker='x', s=15, c="black")plt.show()

聚类的结果:不同颜色表示不同类型

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
当然,我可以为您提供一个基于 PyTorch 的 DBSCAN 聚类算法的代码示例。DBSCAN 是一种基于密度的聚类算法,可以有效地发现具有足够密度的区域。以下是使用 PyTorch 实现的 DBSCAN 聚类算法代码: ```python import torch import numpy as np def dbscan(X, epsilon, min_pts): """ :param X: 数据集(PyTorch Tensor) :param epsilon: 邻域半径 :param min_pts: 邻域中最小点数 :return: 聚类结果(PyTorch Tensor) """ visited = torch.zeros(X.size(0), dtype=torch.bool) noise = torch.zeros(X.size(0), dtype=torch.bool) clusters = [] cluster_id = 0 for point_id in range(X.size(0)): if visited[point_id]: continue visited[point_id] = True neighbors = region_query(X, point_id, epsilon) if neighbors.size(0) < min_pts: noise[point_id] = True else: cluster = expand_cluster(X, point_id, neighbors, epsilon, min_pts, visited) clusters.append(cluster) cluster_id += 1 return torch.cat(clusters), noise def region_query(X, point_id, epsilon): """ 找到给定点的 epsilon-邻域内所有的点 :param X: 数据集(PyTorch Tensor) :param point_id: 给定点的索引 :param epsilon: 邻域半径 :return: 邻域内的点的索引(PyTorch Tensor) """ return torch.nonzero(torch.sum((X - X[point_id])**2, dim=1) <= epsilon**2).squeeze() def expand_cluster(X, point_id, neighbors, epsilon, min_pts, visited): """ 从给定点开始拓展聚类 :param X: 数据集(PyTorch Tensor) :param point_id: 给定点的索引 :param neighbors: 邻域内的点的索引(PyTorch Tensor) :param epsilon: 邻域半径 :param min_pts: 邻域中最小点数 :param visited: 记录是否访问的标志(PyTorch Tensor) :return: 聚类结果(PyTorch Tensor) """ cluster = [point_id] for neighbor_id in neighbors: if not visited[neighbor_id]: visited[neighbor_id] = True new_neighbors = region_query(X, neighbor_id, epsilon) if new_neighbors.size(0) >= min_pts: neighbors = torch.cat((neighbors, new_neighbors)) if neighbor_id.item() not in [point.item() for point in cluster]: cluster.append(neighbor_id.item()) return torch.tensor(cluster) # 示例使用 X = torch.tensor([[1.0, 1.0], [1.5, 2.0], [3.0, 4.0], [5.0, 7.0], [3.5, 5.0], [4.5, 5.0], [3.5, 4.5]]) epsilon = 0.5 min_pts = 3 clusters, noise = dbscan(X, epsilon, min_pts) print("聚类结果:", clusters) print("噪音点:", noise) ``` 在这个示例中,我们使用纯 PyTorch 实现了 DBSCAN 聚类算法。首先定义了三个辅助函数:`region_query` 用于找到给定点的 epsilon-邻域内的所有点,`expand_cluster` 用于从给定点开始拓展聚类,`dbscan` 是 DBSCAN 算法的主要实现函数。 然后我们给出了一个数据集的示例,并调用 `dbscan` 函数进行聚类。最后打印出聚类结果和噪音点。 请注意,这只是一个简单的示例,实际应用中可能需要根据具体情况对代码进行修改和优化。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值