tensorflow_kmeans

本文介绍了一种基于 TensorFlow 的 K-Means 聚类算法实现方法,通过 Python 代码展示了如何构建计算图并进行迭代聚类,最后通过 seaborn 对聚类结果进行了可视化。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

# -*- coding: utf-8 -*-
import numpy as np
from numpy.linalg import cholesky
import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd
import tensorflow as tf
from random import choice, shuffle
from numpy import array
############Sachin Joglekar的基于tensorflow写的一个kmeans模板###############
def KMeansCluster(vectors, noofclusters):
    """
    K-Means Clustering using TensorFlow.
    `vertors`应该是一个n*k的二维的NumPy的数组,其中n代表着K维向量的数目
    'noofclusters' 代表了待分的集群的数目,是一个整型值
    """

    noofclusters = int(noofclusters)
    assert noofclusters < len(vectors)
    #找出每个向量的维度
    dim = len(vectors[0])
    #辅助随机地从可得的向量中选取中心点
    vector_indices = list(range(len(vectors)))
    shuffle(vector_indices)
    #计算图
    #我们创建了一个默认的计算流的图用于整个算法中,这样就保证了当函数被多次调用      #时,默认的图并不会被从上一次调用时留下的未使用的OPS或者Variables挤满
    graph = tf.Graph()
    with graph.as_default():
        #计算的会话
        sess = tf.Session()
        ##构建基本的计算的元素
        ##首先我们需要保证每个中心点都会存在一个Variable矩阵
        ##从现有的点集合中抽取出一部分作为默认的中心点
        centroids = [tf.Variable((vectors[vector_indices[i]]))
                     for i in range(noofclusters)]
        ##创建一个placeholder用于存放各个中心点可能的分类的情况
        centroid_value = tf.placeholder("float64", [dim])
        cent_assigns = []
        for centroid in centroids:
            cent_assigns.append(tf.assign(centroid, centroid_value))
        ##对于每个独立向量的分属的类别设置为默认值0
        assignments = [tf.Variable(0) for i in range(len(vectors))]
        ##这些节点在后续的操作中会被分配到合适的值
        assignment_value = tf.placeholder("int32")
        cluster_assigns = []
        for assignment in assignments:
            cluster_assigns.append(tf.assign(assignment,
                                             assignment_value))
        ##下面创建用于计算平均值的操作节点
        #输入的placeholder
        mean_input = tf.placeholder("float", [None, dim])
        #节点/OP接受输入,并且计算0维度的平均值,譬如输入的向量列表
        mean_op = tf.reduce_mean(mean_input, 0)
        ##用于计算欧几里得距离的节点
        v1 = tf.placeholder("float", [dim])
        v2 = tf.placeholder("float", [dim])
        euclid_dist = tf.sqrt(tf.reduce_sum(tf.pow(tf.subtract(v1, v2), 2)))
        ##这个OP会决定应该将向量归属到哪个节点
        ##基于向量到中心点的欧几里得距离
        #Placeholder for input
        centroid_distances = tf.placeholder("float", [noofclusters])
        cluster_assignment = tf.argmin(centroid_distances, 0)
        ##初始化所有的状态值
         ##这会帮助初始化图中定义的所有Variables。Variable-initializer应该定
         ##义在所有的Variables被构造之后,这样所有的Variables才会被纳入初始化
        init_op = tf.global_variables_initializer()
        #初始化所有的变量
        sess.run(init_op)
        ##集群遍历
        #接下来在K-Means聚类迭代中使用最大期望算法。为了简单起见,只让它执行固
        #定的次数,而不设置一个终止条件
        noofiterations = 20
        for iteration_n in range(noofiterations):

            ##期望步骤
            ##基于上次迭代后算出的中心点的未知
            ##the _expected_ centroid assignments.
            #首先遍历所有的向量
            for vector_n in range(len(vectors)):
                vect = vectors[vector_n]
                #计算给定向量与分配的中心节点之间的欧几里得距离
                distances = [sess.run(euclid_dist, feed_dict={
                    v1: vect, v2: sess.run(centroid)})
                             for centroid in centroids]
                #下面可以使用集群分配操作,将上述的距离当做输入
                assignment = sess.run(cluster_assignment, feed_dict = {
                    centroid_distances: distances})
                #接下来为每个向量分配合适的值
                sess.run(cluster_assigns[vector_n], feed_dict={
                    assignment_value: assignment})

            ##最大化的步骤
            #基于上述的期望步骤,计算每个新的中心点的距离从而使集群内的平方和最小
            for cluster_n in range(noofclusters):
                #收集所有分配给该集群的向量
                assigned_vects = [vectors[i] for i in range(len(vectors))
                                  if sess.run(assignments[i]) == cluster_n]
                #计算新的集群中心点
                new_location = sess.run(mean_op, feed_dict={
                    mean_input: array(assigned_vects)})
                #为每个向量分配合适的中心点
                sess.run(cent_assigns[cluster_n], feed_dict={
                    centroid_value: new_location})

        #返回中心节点和分组
        centroids = sess.run(centroids)
        assignments = sess.run(assignments)
        return centroids, assignments
############生成测试数据###############
sampleNo = 100;#数据数量
mu =3
# 二维正态分布
mu = np.array([[1, 5]])
Sigma = np.array([[1, 0.5], [1.5, 3]])
R = cholesky(Sigma)
srcdata= np.dot(np.random.randn(sampleNo, 2), R) + mu
plt.plot(srcdata[:,0],srcdata[:,1],'bo')
############kmeans算法计算###############
k=4
center,result=KMeansCluster(srcdata,k)
print(center)
############利用seaborn画图###############

res={"x":[],"y":[],"kmeans_res":[]}
for i in range(len(result)):
    res["x"].append(srcdata[i][0])
    res["y"].append(srcdata[i][1])
    res["kmeans_res"].append(result[i])
pd_res=pd.DataFrame(res)
sns.lmplot("x","y",data=pd_res,fit_reg=False,size=5,hue="kmeans_res")
plt.show()
<think>我们使用TensorFlowModelOptimizationToolkit(TFMOT)来实现模型优化,包括剪枝、量化和权重聚类。下面我们将展示如何使用TFMOT对TensorFlow模型进行优化,并提供完整的代码示例。</think>### TensorFlow Model Optimization 实战指南 TensorFlow Model Optimization Toolkit (TFMOT) 提供了一系列强大的模型优化技术,以下是完整的优化流程实现: ```python import tensorflow as tf import tensorflow_model_optimization as tfmot import numpy as np import os # 加载数据集 (x_train, y_train), (x_test, y_test) = tf.keras.datasets.mnist.load_data() x_train = x_train.reshape(60000, 28, 28, 1).astype('float32') / 255.0 x_test = x_test.reshape(10000, 28, 28, 1).astype('float32') / 255.0 # 基础模型架构 def create_base_model(): model = tf.keras.Sequential([ tf.keras.layers.Conv2D(16, 3, activation='relu', input_shape=(28, 28, 1)), tf.keras.layers.MaxPooling2D(), tf.keras.layers.Flatten(), tf.keras.layers.Dense(64, activation='relu'), tf.keras.layers.Dense(10, activation='softmax') ]) return model # 1. 剪枝优化 def apply_pruning(model): """应用剪枝优化""" # 定义剪枝参数 pruning_params = { 'pruning_schedule': tfmot.sparsity.keras.PolynomialDecay( initial_sparsity=0.30, # 初始稀疏度 final_sparsity=0.80, # 最终稀疏度 begin_step=0, end_step=1000 ), 'block_size': (1, 1), # 块稀疏结构 'block_pooling_type': 'AVG' } # 应用剪枝 model_pruned = tfmot.sparsity.keras.prune_low_magnitude(model, **pruning_params) # 添加剪枝回调 callbacks = [ tfmot.sparsity.keras.UpdatePruningStep() ] return model_pruned, callbacks # 2. 量化感知训练 def apply_quantization_aware_training(model): """应用量化感知训练""" quantize_model = tfmot.quantization.keras.quantize_model model_quantized = quantize_model(model) return model_quantized # 3. 权重聚类 def apply_weight_clustering(model, num_clusters=16): """应用权重聚类""" clustering_params = { 'number_of_clusters': num_clusters, 'cluster_centroids_init': tfmot.clustering.keras.CentroidInitialization.KMEANS_PLUS_PLUS } # 聚类整个模型 clustered_model = tfmot.clustering.keras.cluster_weights(model, **clustering_params) return clustered_model # 4. 训练和评估函数 def train_and_evaluate(model, name, callbacks=None): """训练并评估模型""" print(f"\n===== 训练 {name} 模型 =====") # 编译模型 model.compile( optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'] ) # 训练模型 history = model.fit( x_train, y_train, epochs=5, validation_split=0.2, batch_size=128, callbacks=callbacks if callbacks else [] ) # 评估模型 _, accuracy = model.evaluate(x_test, y_test, verbose=0) print(f"{name} 测试准确率: {accuracy:.4f}") # 保存模型 model.save(f"{name}.h5") # 计算模型大小 size_bytes = os.path.getsize(f"{name}.h5") size_mb = size_bytes / (1024 * 1024) print(f"{name} 模型大小: {size_mb:.2f} MB") return model, accuracy, size_mb # 5. 量化转换 def convert_to_tflite(model, model_name, quantize_mode='default'): """转换为TFLite格式""" converter = tf.lite.TFLiteConverter.from_keras_model(model) # 设置优化选项 if quantize_mode == 'float16': converter.optimizations = [tf.lite.Optimize.DEFAULT] converter.target_spec.supported_types = [tf.float16] elif quantize_mode == 'full_int8': converter.optimizations = [tf.lite.Optimize.DEFAULT] converter.representative_dataset = lambda: representative_data_gen() elif quantize_mode == 'dynamic_range': converter.optimizations = [tf.lite.Optimize.DEFAULT] # 转换为TFLite tflite_model = converter.convert() # 保存模型 tflite_path = f"{model_name}_{quantize_mode}.tflite" with open(tflite_path, 'wb') as f: f.write(tflite_model) # 获取模型大小 size_bytes = os.path.getsize(tflite_path) size_mb = size_bytes / (1024 * 1024) print(f"{tflite_path} 大小: {size_mb:.2f} MB") return tflite_path, size_mb def representative_data_gen(): """生成代表性数据集用于量化""" for i in range(100): yield [x_test[i:i+1].astype(np.float32)] # 6. 性能测试 def benchmark_tflite(model_path): """基准测试TFLite模型性能""" # 加载TFLite模型 interpreter = tf.lite.Interpreter(model_path=model_path) interpreter.allocate_tensors() # 获取输入输出信息 input_details = interpreter.get_input_details() output_details = interpreter.get_output_details() # 准备测试数据 input_shape = input_details[0]['shape'] total_time = 0 correct = 0 # 运行100次推理 for i in range(100): input_data = x_test[i:i+1].astype(np.float32) interpreter.set_tensor(input_details[0]['index'], input_data) # 执行推理并计时 start = tf.timestamp() interpreter.invoke() end = tf.timestamp() total_time += (end - start).numpy() # 获取输出 output = interpreter.get_tensor(output_details[0]['index']) pred = np.argmax(output) if pred == y_test[i]: correct += 1 # 计算指标 accuracy = correct / 100 avg_latency = total_time / 100 * 1000 # 转换为毫秒 print(f"模型: {os.path.basename(model_path)}") print(f"准确率: {accuracy:.4f} | 平均延迟: {avg_latency:.2f} ms") return accuracy, avg_latency # 主优化流程 def full_optimization_pipeline(): # 创建基础模型 base_model = create_base_model() # 训练基础模型 base_model, base_acc, base_size = train_and_evaluate(base_model, "base_model") # 应用剪枝 pruned_model, pruning_callbacks = apply_pruning(create_base_model()) pruned_model, pruned_acc, pruned_size = train_and_evaluate( pruned_model, "pruned_model", callbacks=pruning_callbacks ) # 应用量化感知训练 qat_model = apply_quantization_aware_training(create_base_model()) qat_model, qat_acc, qat_size = train_and_evaluate(qat_model, "qat_model") # 应用权重聚类 clustered_model = apply_weight_clustering(create_base_model()) clustered_model, clustered_acc, clustered_size = train_and_evaluate( clustered_model, "clustered_model" ) # 组合优化:剪枝 + 量化 pruned_qat_model = apply_quantization_aware_training(pruned_model) pruned_qat_model, pruned_qat_acc, pruned_qat_size = train_and_evaluate( pruned_qat_model, "pruned_qat_model" ) # 转换为TFLite并量化 models = { "base": base_model, "pruned": pruned_model, "qat": qat_model, "clustered": clustered_model, "pruned_qat": pruned_qat_model } # 测试不同量化模式 results = [] for name, model in models.items(): # 默认量化 tflite_path, tflite_size = convert_to_tflite(model, name, 'dynamic_range') acc, latency = benchmark_tflite(tflite_path) results.append({ "name": name + "_dynamic", "accuracy": acc, "size_mb": tflite_size, "latency_ms": latency }) # float16量化 tflite_path, tflite_size = convert_to_tflite(model, name, 'float16') acc, latency = benchmark_tflite(tflite_path) results.append({ "name": name + "_float16", "accuracy": acc, "size_mb": tflite_size, "latency_ms": latency }) # 全整型量化 if name in ["qat", "pruned_qat"]: # 仅量化感知训练的模型支持全整型 tflite_path, tflite_size = convert_to_tflite(model, name, 'full_int8') acc, latency = benchmark_tflite(tflite_path) results.append({ "name": name + "_int8", "accuracy": acc, "size_mb": tflite_size, "latency_ms": latency }) return results # 运行优化流程 if __name__ == "__main__": optimization_results = full_optimization_pipeline() # 打印结果摘要 print("\n===== 优化结果摘要 =====") print(f"{'模型名称':<20}{'大小(MB)':<10}{'延迟(ms)':<12}{'准确率':<8}") for result in optimization_results: print(f"{result['name']:<20}{result['size_mb']:<10.2f}{result['latency_ms']:<12.2f}{result['accuracy']:<8.4f}") ``` ### 优化技术详解 #### 1. 剪枝(Pruning) ```python # 应用剪枝 pruning_params = { 'pruning_schedule': tfmot.sparsity.keras.PolynomialDecay( initial_sparsity=0.30, final_sparsity=0.80, begin_step=0, end_step=1000 ) } model_pruned = tfmot.sparsity.keras.prune_low_magnitude(model, **pruning_params) ``` - **原理**:逐步移除对模型输出影响小的权重 - **优点**:减少模型大小,加速推理 - **实现**:使用`PolynomialDecay`计划逐渐增加稀疏度 #### 2. 量化感知训练(Quantization-Aware Training) ```python # 应用量化感知训练 quantize_model = tfmot.quantization.keras.quantize_model model_quantized = quantize_model(model) ``` - **原理**:在训练中模拟量化效果,让模型适应低精度 - **优点**:减少模型大小4倍,加速推理2-3倍 - **实现**:在训练中插入伪量化节点 #### 3. 权重聚类(Weight Clustering) ```python # 应用权重聚类 clustering_params = { 'number_of_clusters': 16, 'cluster_centroids_init': tfmot.clustering.keras.CentroidInitialization.KMEANS_PLUS_PLUS } clustered_model = tfmot.clustering.keras.cluster_weights(model, **clustering_params) ``` - **原理**:将权重分组到聚类中心,减少唯一权重值数量 - **优点**:显著减少模型大小,提高压缩率 - **实现**:使用k-means++算法初始化聚类中心 ### TFLite 量化技术 #### 1. 动态范围量化 ```python converter.optimizations = [tf.lite.Optimize.DEFAULT] ``` - **原理**:仅量化权重为int8,激活保持float32 - **优点**:减少模型大小4倍,精度损失小 #### 2. Float16量化 ```python converter.optimizations = [tf.lite.Optimize.DEFAULT] converter.target_spec.supported_types = [tf.float16] ``` - **原理**:将权重转换为float16 - **优点**:减少模型大小2倍,支持GPU加速 #### 3. 全整型量化 ```python converter.optimizations = [tf.lite.Optimize.DEFAULT] converter.representative_dataset = lambda: representative_data_gen() ``` - **原理**:权重和激活都量化为int8 - **优点**:最大化性能和能效,适合低功耗设备 - **要求**:需要代表性数据集校准量化参数 ### 优化结果对比(示例) | 模型类型 | 大小(MB) | 延迟(ms) | 准确率 | |-----------------|----------|----------|--------| | base_dynamic | 1.85 | 12.4 | 0.978 | | base_float16 | 0.92 | 8.7 | 0.978 | | pruned_dynamic | 0.76 | 9.2 | 0.976 | | qat_int8 | 0.48 | 6.3 | 0.975 | | pruned_qat_int8 | 0.31 | 4.8 | 0.972 | ### 高级优化技巧 #### 1. 分层优化策略 ```python # 为不同层应用不同优化 def selective_optimization(model): # 只量化密集层 quantize_annotate_layer = tfmot.quantization.keras.quantize_annotate_layer quantize_annotate_model = tfmot.quantization.keras.quantize_annotate_model # 标注要量化的层 annotated_model = quantize_annotate_model(model) for layer in annotated_model.layers: if isinstance(layer, tf.keras.layers.Dense): annotated_model = quantize_annotate_layer(layer) # 应用量化 return tfmot.quantization.keras.quantize_apply(annotated_model) ``` #### 2. 稀疏聚类联合优化 ```python # 先剪枝后聚类 def combined_optimization(model): # 应用剪枝 pruned_model = apply_pruning(model) # 微调剪枝模型 pruned_model.fit(...) # 移除剪枝包装 stripped_pruned_model = tfmot.sparsity.keras.strip_pruning(pruned_model) # 应用聚类 clustered_model = apply_weight_clustering(stripped_pruned_model) return clustered_model ``` #### 3. 模型蒸馏 ```python def model_distillation(teacher_model, student_model): # 教师模型生成软标签 teacher_logits = teacher_model.predict(x_train) # 定义蒸馏损失 def distillation_loss(y_true, y_pred): # 真实标签损失 ce_loss = tf.keras.losses.sparse_categorical_crossentropy(y_true, y_pred) # 教师-学生蒸馏损失 teacher_probs = tf.nn.softmax(teacher_logits / 2.0) student_probs = tf.nn.softmax(y_pred / 2.0) kl_loss = tf.keras.losses.kld(teacher_probs, student_probs) return 0.3 * ce_loss + 0.7 * kl_loss # 编译学生模型 student_model.compile( optimizer='adam', loss=distillation_loss ) return student_model ``` ### 生产环境部署建议 1. **移动端部署**: ```java // Android TFLite部署示例 Interpreter.Options options = new Interpreter.Options(); options.setUseNNAPI(true); // 启用硬件加速 Interpreter interpreter = new Interpreter(modelFile, options); interpreter.run(inputBuffer, outputBuffer); ``` 2. **Web部署**: ```html <!-- TensorFlow.js部署 --> <script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs"></script> <script> async function loadModel() { const model = await tf.loadGraphModel('model_web/model.json'); const input = tf.tensor4d(imageData, [1, 224, 224, 3]); const output = model.predict(input); const result = output.argMax(1).dataSync()[0]; } </script> ``` 3. **边缘设备部署**: ```cpp // Raspberry Pi C++部署 #include "tensorflow/lite/interpreter.h" #include "tensorflow/lite/model.h" std::unique_ptr<tflite::FlatBufferModel> model = tflite::FlatBufferModel::BuildFromFile("model.tflite"); tflite::ops::builtin::BuiltinOpResolver resolver; std::unique_ptr<tflite::Interpreter> interpreter; tflite::InterpreterBuilder(*model, resolver)(&interpreter); interpreter->AllocateTensors(); float* input = interpreter->typed_input_tensor<float>(0); // 填充输入数据... interpreter->Invoke(); float* output = interpreter->typed_output_tensor<float>(0); ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AI算法网奇

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值