【论文阅读】Self-paced Multi-view Co-training

news2025/2/25 22:11:48

论文下载
bib:

@ARTICLE{MaMeng2020SPamCo,
title 		= {Self-Paced Multi-View Co-Training},
author 		= {Fan Ma and Deyu Meng and Xuanyi Dong and Yi Yang},
journal 	= {J. Mach. Learn. Res.},
year 		= {2020},
volume 		= {21},
number 		= {1},
numpages 	= {1--38}
}

目录

  • 1. 摘要
  • 2. 算法描述
  • 3. 具体算法
    • 3.1. Serial SPamCo Algorithm
    • 3.2. Parallel SPamCo Algorithm
  • 4. Toy Example
  • 5. 总结

1. 摘要

Co-training is a well-known semi-supervised learning approach which trains classifiers on two or more different views and exchanges pseudo labels of unlabeled instances in an iterative way.

提纲挈领的第一句。(八股文)

During the co-training process, pseudo labels of unlabeled instances are very likely to be false especially in the initial training, while the standard co-training algorithm adopts a “draw without replacement” strategy and does not remove these wrongly labeled instances from training stages.

指出现有方法的不足,第一点: 初始伪标签质量差,现有的方法不会替换(更新)以前打的伪标签。值得注意的是,一般只会提出一项不足,这篇论文提出了三点,这也意味着跟多的贡献点。

Besides, most of the traditional co-training approaches are implemented for two-view cases, and their extensions in multi-view scenarios are not intuitive.

These issues not only degenerate their performance as well as available application range but also hamper their fundamental theory.

第二点不足:现有方法大多针对两个视图,不能直观的拓展到多个视图。

Moreover, there is no optimization model to explain the objective a co-training process manages to optimize.

第三点不足:没有一个优化模型来解释一个协同训练过程管理优化的目标。

To address these issues, in this study we design a unified self-paced multi-view co-training (SPamCo) framework which draws unlabeled instances with replacement.
Two specified co-regularization terms are formulated to develop different strategies for selecting pseudo-labeled instances during training.

提出方案处理第一个不足,方案会替换前期打的伪标签(draws unlabeled instances with replacement)。

Both forms share the same optimization strategy which is consistent with the iteration process in co-training and can be naturally extended to multi-view scenarios.

处理第二个不足,能自然的拓展到多视图(不局限于两个视图)。隐含处理了第三个不足(optimization strategy)。

A distributed optimization strategy is also introduced to train the classifier of each view in parallel to further improve the efficiency of the algorithm.

额外的并行优化方案。

Furthermore, the SPamCo algorithm is proved to be PAC learnable, supporting its theoretical soundness.

Experiments conducted on synthetic, text categorization, person re-identification, image recognition and object detection data sets substantiate the superiority of the proposed method.

2. 算法描述

SPamCo: optimization problem
min ⁡ Θ , V , Y ~ ∑ j = 1 M ( ∑ i = 1 N l ℓ i ( j ) + ∑ i = N l + 1 N l + N u ( v i ( j ) ℓ i ( j ) + f ( v i ( j ) , λ ( j ) ) ) + R ( Θ ) + R ( V ) (1) \min_{\Theta, \bm{V}, \widetilde{\bm{Y}}}\sum_{j=1}^M{( \sum_{i=1}^{N_l}\ell_i^{(j)}+\sum_{i=N_l+1}^{N_l+N_u}{(v_i ^{(j)}\ell_i^{(j)}+f(v_i^{(j)},\lambda^{(j)})}) + \mathcal{R}(\Theta})+\mathcal{R}(\bm{V}) \tag{1} Θ,V,Y minj=1M(i=1Nli(j)+i=Nl+1Nl+Nu(vi(j)i(j)+f(vi(j),λ(j)))+R(Θ)+R(V)(1)

Self-paced Regularization term:

f ( v i ( j ) , λ ( j ) ) = − λ ( j ) v i ( j ) (2) f(v_i^{(j)},\lambda^{(j)}) = -\lambda^{(j)}v_i^{(j)} \tag{2} f(vi(j),λ(j))=λ(j)vi(j)(2)

Co-Regularization Term:

  • hard:

R h ( V ) = − γ ∑ p < q ( v ( p ) ) T v ( q ) \mathcal{R}_h(\bm{V}) = -\gamma\sum_{p<q}({v}^{(p)})^{\mathsf{T}}{v}^{(q)} Rh(V)=γp<q(v(p))Tv(q)

v i ( j ) ∗ = { 1 , ℓ i j < λ c ( j ) + γ ∑ p ≠ j v i p ; 0 , otherwise . v_i^{(j)*} = \begin{cases} 1, \ell_i^{{j}}<\lambda_c^{(j)}+\gamma\sum_{p\neq j}{v_i^{p}};\\ 0, \text{otherwise}. \end{cases} vi(j)={1,ij<λc(j)+γp=jvip;0,otherwise.

  • soft:

R s ( V ) = − γ ∑ p < q ( v ( p ) − v ( q ) ) T ( v ( p ) − v ( q ) ) \mathcal{R}_s(\bm{V}) = -\gamma\sum_{p<q}({v}^{(p)}-{v}^{(q)})^{\mathsf{T}}{({v}^{(p)} - {v}^{(q)})} Rs(V)=γp<q(v(p)v(q))T(v(p)v(q))
与硬正则之间的重要区别是,硬正则是只有选或者不选,别的视图选了,那么该样本在本视图中有更大的可能被选择。而软正则是说, v i ( j ) ∈ [ 0 , 1 ] v_i^{(j)}\in [0, 1] vi(j)[0,1],表示0到1的实数,软正则要求两者的选择逼近(类似与均方误差)。

v i ( j ) ∗ = { 0 , ℓ i j ≥ λ c ( j ) + γ ∑ p ≠ j v i p ; 1 , ℓ i j ≥ λ c ( j ) + γ ∑ p ≠ j ( v i p − 1 ) ; 1 M − 1 ( ∑ p ≠ j v i p + λ c j − ℓ i ( j ) γ ) , otherwise . v_i^{(j)*} = \begin{cases} 0, \ell_i^{{j}} \geq \lambda_c^{(j)}+\gamma\sum_{p\neq j}{v_i^{p}};\\ 1, \ell_i^{{j}} \geq \lambda_c^{(j)}+\gamma\sum_{p\neq j}{(v_i^{p}-1)};\\ \frac{1}{M-1}(\sum_{p\neq j}{v_i^{p}}+ \frac{\lambda_c^{j}-\ell_i^{(j)}}{\gamma}), \text{otherwise}.\\ \end{cases} vi(j)= 0,ijλc(j)+γp=jvip;1,ijλc(j)+γp=j(vip1);M11(p=jvip+γλcji(j)),otherwise.

3. 具体算法

3.1. Serial SPamCo Algorithm

串行版本的SPamCo,体现在每个视图串行更新。
在这里插入图片描述
Note:
这里有一点让我很在意,就是为什么伪代码中的 v ( vid ) \bm{v}^{(\text{vid})} v(vid)要更新两次。主要的原因在于,模型在其中发生了更新,而 v ( vid ) \bm{v}^{(\text{vid})} v(vid)与模型的当前预测密切相关。也可以看作,第一次更新 v ( vid ) \bm{v}^{(\text{vid})} v(vid)是为了更新当前视图的模型参数,第二次更新 v ( vid ) \bm{v}^{(\text{vid})} v(vid)是为了选择自己自信的无标记样本给其他的视图。

3.2. Parallel SPamCo Algorithm

串行版本的SPamCo,体现在每个视图并行更新,用其他视图的上一个版本的 v i , t − 1 ( j ) v_{i,t-1}^{(j)} vi,t1(j)来更新当前版本当前视图的 v i , t ( m ) v_{i,t}^{(m)} vi,t(m)
在这里插入图片描述

4. Toy Example

Github

from sklearn.datasets import make_moons, make_classification, make_circles, make_blobs
import matplotlib.pyplot as plt
import matplotlib.pylab as plb
import numpy as np
from itertools import cycle, islice
import matplotlib
import warnings
from matplotlib.ticker import MaxNLocator
import copy
from sklearn.tree import DecisionTreeClassifier
from sklearn.svm import LinearSVC, SVC, NuSVC
from copy import deepcopy

warnings.filterwarnings("ignore")
# matplotlib.rcParams.update({'font.size': 10})


def sel_ids_y(score, add_num=10):
    ids_sort = np.argsort(score)
    add_id = np.zeros(score.shape[0])
    add_id[ids_sort[:add_num]] = -1
    add_id[ids_sort[-add_num:]] = 1
    # 同时获取前add_num和后add_num个样本为负正样本
    return add_id


def update_train_untrain(sel_ids, train_data, train_labels, untrain_data, weights=None):
    #  sel_ids = np.array(sel_ids, dtype='bool')
    add_ids = np.where(np.array(sel_ids) != 0)[0]
    untrain_ids = np.where(np.array(sel_ids) == 0)[0]
    add_datas = [d[add_ids] for d in untrain_data]
    new_train_data = [np.concatenate([d1, d2]) for d1, d2 in zip(train_data, add_datas)]
    add_y = [1 if sel_ids[idx] > 0 else 0 for idx in add_ids]
    new_train_y = np.concatenate([train_labels, add_y])
    new_untrain_data = [d[untrain_ids] for d in untrain_data]
    return new_train_data, new_train_y, new_untrain_data


def cotrain(labeled_data, labels, unlabeled_data, iter_step=1):
    lbls = copy.deepcopy(labels)
    for step in range(iter_step):
        scores = []
        add_ids = []
        add_ys = []
        clfs = []
        for view in range(2):
            clfs.append(LinearSVC())
            clfs[view].fit(labeled_data[view], lbls)
            scores.append(clfs[view].decision_function(unlabeled_data[view]))
            add_id = sel_ids_y(scores[view], 6)
            add_ids.append(add_id)
        add_id = sum(add_ids)
        labeled_data, lbls, unlabeled_data = update_train_untrain(add_id, labeled_data, lbls, unlabeled_data)
        if len(unlabeled_data[view]) <= 0:
            break
    return clfs


def update_train(sel_ids, train_data, train_labels, untrain_data, pred_y):
    add_ids = np.where(np.array(sel_ids) != 0)[0]
    add_data = [d[add_ids] for d in untrain_data]
    new_train_data = [np.concatenate([d1, d2]) for d1, d2 in zip(train_data, add_data)]
    add_y = pred_y[add_ids]
    new_train_y = np.concatenate([train_labels, pred_y[add_ids]])
    return new_train_data, new_train_y


def spaco(l_data, lbls, u_data, iter_step=1, gamma=0.5):
    # initiate classifier
    clfs = []
    scores = []
    add_ids = []
    add_num = 6
    clfss = []
    # initial
    for view in range(2):
        clfs.append(LinearSVC())
        clfs[view].fit(l_data[view], lbls)
        scores.append(clfs[view].decision_function(u_data[view]))
        add_ids.append(sel_ids_y(scores[view], add_num))
        # 置信度大于0,则为正样本;置信度为负,则为负样本
        py = [0 if s < 0 else 1 for s in scores[view]]
    score = sum(scores)
    pred_y = np.array([0 if s < 0 else 1 for s in score])
    # for each step
    for step in range(iter_step):
        # for each view
        for view in range(2):
            # 如果无标记样本不足,推出循环
            if add_num * 2 > u_data[0].shape[0]:
                break
            # update v
            ov = np.where(add_ids[1 - view] != 0)[0]
            scores[view][ov] += add_ids[1 - view][ov] * gamma
            add_ids[view] = sel_ids_y(scores[view], add_num)

            # update w
            nl_data, nlbls = update_train(add_ids[view], l_data, lbls, u_data, pred_y)
            clfs[view].fit(nl_data[view], nlbls)

            # update y, v
            scores[view] = clfs[view].decision_function(u_data[view])
            add_num += 6
            # 为什么要做这一步,是应为scores[view]这一步在更新y的时候发生了改变
            # 值得注意的是,这个不算重复计算
            scores[view][ov] += add_ids[1 - view][ov] * gamma
            add_ids[view] = sel_ids_y(scores[view], add_num)

            score = sum(scores)

            pred_y = np.array([0 if s < 0 else 1 for s in score])
            py = [0 if s < 0 else 1 for s in scores[view]]
    return clfs


def main():
    # toy 2
    np.random.seed(4)
    X, y = make_blobs(n_samples=400, centers=2, cluster_std=0.7)
    X[:, 0] -= 9.3
    X[:, 1] -= 2.5

    np.random.seed(1)
    pos_ids = np.where(y == 0)[0]
    neg_ids = np.where(y == 1)[0]
    ids1 = np.random.randint(0, len(pos_ids), 5)
    ids2 = np.random.randint(0, len(neg_ids), 5)
    # 正负样本各选了五个点
    p1 = pos_ids[ids1]
    p2 = neg_ids[ids2]

    # generate labeled and unlabeled data
    l_ids = np.concatenate((p1, p2))
    u_ids = np.array(list(set(np.arange(X.shape[0])) - set(l_ids)))
    l_data1, l_data2 = X[l_ids, 0].reshape(-1, 1), X[l_ids, 1].reshape(-1, 1)
    u_data1, u_data2 = X[u_ids, 0].reshape(-1, 1), X[u_ids, 1].reshape(-1, 1)
    labels = y[l_ids]

    colors = np.array(list(islice(cycle(['#377eb8', '#ff7f00', '#4daf4a',
                                         '#f781bf', '#a65628', '#984ea3',
                                         '#999999', '#e41a1c', '#dede00']),
                                  int(max(y) + 3))))

    x = [-1.5, 0, 1.5]
    my_xticks = [-2, 0, 2]

    ### parameters
    # steps = 16
    steps = 30
    gamma = 3

    ### original fig
    fig = plt.figure(figsize=(12, 12))
    plt.subplots_adjust(bottom=.05, top=.9, left=.05, right=0.9)

    ax = fig.add_subplot(141)
    plt.scatter(X[:, 0], X[:, 1], marker='o', c=colors[y], s=4)
    plt.scatter(X[p1, 0], X[p1, 1], marker='^', c='#0F0F0F', s=100)
    plt.scatter(X[p2, 0], X[p2, 1], marker='*', c='#0F0F0F', s=100)
    ax.set_xlabel('$x^{(1)}$')
    ax.set_ylabel('$x^{(2)}$')
    plt.xticks(x, my_xticks)

    #### cotrain experiment
    clfs = cotrain([l_data1, l_data2], labels, [u_data1, u_data2], iter_step=steps)
    score1 = clfs[0].decision_function(X[:, 0].reshape(-1, 1))
    score2 = clfs[1].decision_function(X[:, 1].reshape(-1, 1))
    score = score1 + score2
    pred_y = np.array([0 if s < 0 else 1 for s in score])
    print('cotrain:', np.mean(pred_y == y))

    ax = fig.add_subplot(142)
    ax.set_xlabel('$x^{(1)}$')
    ax.set_ylabel('$x^{(2)}$')
    plt.scatter(X[:, 0], X[:, 1], marker='o', c=colors[pred_y], s=4)

    #### spaco experiment1 gamma=3
    clfs = spaco([l_data1, l_data2], labels, [u_data1, u_data2], iter_step=steps, gamma=3)
    score1 = clfs[0].decision_function(X[:, 0].reshape(-1, 1))
    score2 = clfs[1].decision_function(X[:, 1].reshape(-1, 1))
    score = score1 + score2
    pred_y = np.array([0 if s < 0 else 1 for s in score])
    print('spaco experiment(gamma=3): %0.5f' % np.mean(pred_y == y))
    ax = fig.add_subplot(143)
    ax.set_xlabel('$x^{(1)}$')
    ax.set_ylabel('$x^{(2)}$')
    plt.scatter(X[:, 0], X[:, 1], marker='o', c=colors[pred_y], s=4)
    plt.xticks(x, my_xticks)

    #### spaco experiment2 gamma=0.3
    clfs = spaco([l_data1, l_data2], labels, [u_data1, u_data2], iter_step=steps, gamma=0.3)
    score1 = clfs[0].decision_function(X[:, 0].reshape(-1, 1))
    score2 = clfs[1].decision_function(X[:, 1].reshape(-1, 1))
    score = score1 + score2
    pred_y = np.array([0 if s < 0 else 1 for s in score])
    print('spaco experiment(gamma=0.3): %0.5f' % np.mean(pred_y == y))
    ax = fig.add_subplot(144)
    ax.set_xlabel('$x^{(1)}$')
    ax.set_ylabel('$x^{(2)}$')
    plt.scatter(X[:, 0], X[:, 1], marker='o', c=colors[pred_y], s=4)
    plt.xticks(x, my_xticks)

    plt.show()


if __name__ == '__main__':
    main()

5. 总结

全文读下来,这是一篇很完整的工作,从上到下透露出严谨。本文的核心是将self-pacedmuti-viewco-train糅合在一起,用清晰的数学优化目标表达出来了,特别是Co-Regularization的设计,简洁又漂亮。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/416007.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Kubernetes中的Calico网络

文章目录1 介绍2 环境部署3 IPIP模式3.1 测试环境3.2 ping包网络转发4 BGP模式4.1 测试环境4.2 ping网络转发5 两种模式对比1 介绍 Calico网络的大概思路&#xff0c;即不走Overlay网络&#xff0c;不引入另外的网络性能损耗&#xff0c;而是将转发全部用三层网络的路由转发来…

GPSS【实践 01】Developing a Greenplum Streaming Server Client 自定义GPSS客户端开发实例

自定义GPSS客户端开发流程1.GPSS是什么2.架构3.组件下载安装4.自定义客户端4.1 GPSS Batch Data API Service Definition4.2 Setting up a Java Development Environment4.3 Generating the Batch Data API Client Classes4.4 Coding the GPSS Batch Data Client4.4.1 Connect …

【论文笔记】Attention Augmented Convolutional Networks(ICCV 2019 入选文章)

目录 一、摘要 二、介绍 三、相关工作 卷积网络Convolutional networks&#xff1a; 网络中注意力机制Attention mechanisms in networks&#xff1a; 四、方法 1. 图像的自注意力Self-attention over images&#xff1a; 二维位置嵌入Two-dimensional Positional Enco…

redis 第一章

开始学习redis 之旅吧 关于redis 的介绍 redis 是一个开源的软件&#xff0c;可以存储结构化的数据在内存中&#xff0c;像内存数据库&#xff0c;缓存、消息中间件、流处理引擎。 redis 提供的数据结构像strings, hashes, lists, sets, sorted sets 。Redis具有内置复制、Lua…

《花雕学AI》13:早出对策,积极应对ChatGPT带来的一系列风险和挑战

ChatGPT是一款能和人类聊天的机器人&#xff0c;它可以学习和理解人类语言&#xff0c;也可以帮人们做一些工作&#xff0c;比如翻译、写文章、写代码等。ChatGPT很强大&#xff0c;让很多人感兴趣&#xff0c;也让很多人担心。 使用ChatGPT有一些风险&#xff0c;比如数据的质…

Pytorch 张量操作 Python切片操作

目录一维张量定义一维实例操作二维张量操作张量拼接-注意需要拼接的维度一定要相同广播机制更高维的演示总结YOLOv5 Focus样例参考梳理一下Pytorch的张量切片操作一维张量定义 一维向量的操作其实很像numpy一维数组&#xff0c;基本定义如下&#xff1a; 1.默认步长为1 2.起始…

HotSpot经典垃圾收集器

虽然垃圾收集器的技术在不断进步&#xff0c;但直到现在还没最好的收集器出现&#xff0c;更加不存在“万能”的收集器&#xff0c;所以我们选择的只是对具体应用最合适的收集器。 图 HotSpot中的垃圾收集器&#xff0c;连线表示可搭配使用 1 Serial收集器 是最基础、历史最悠…

第08章_面向对象编程(高级)

第08章_面向对象编程(高级) 讲师&#xff1a;尚硅谷-宋红康&#xff08;江湖人称&#xff1a;康师傅&#xff09; 官网&#xff1a;http://www.atguigu.com 本章专题与脉络 1. 关键字&#xff1a;static 回顾类中的实例变量&#xff08;即非static的成员变量&#xff09; c…

linux文件类型和根目录结构

目录 一、Linux文件类型 二、Linux系统的目录结构 1. FHS 2. 路径以及工作目录 &#xff08;1&#xff09;路径 &#xff08;2&#xff09;工作目录 一、Linux文件类型 使用ls -l命令查看到的第一个字符文件类型说明-普通文件类似于Windows的记事本d目录文件类似于Windo…

【GPT4】GPT4 创作郭德纲姜昆相声作品的比较研究

欢迎关注【youcans的 AIGC 学习笔记】原创作品 说明&#xff1a;本文附录内容由 youcans 与 GPT-4 共同创作。 【GPT4】GPT4 创作郭德纲姜昆相声作品的比较研究研究总结0. 背景1. 对 GPT4 创作的第 1 段相声的分析2. 对GPT4 创作的第 2 段相声的分析3. 对GPT4 创作的第 3 段相…

Window常用命令

一、快捷键 1、自带快捷键 序号快捷键作用1windowsGXBOX录屏2cmd >osk屏幕键盘3cmd >calc计算器4cmd >mrt恶意软件删除工具 2、浏览器快捷键 序号快捷键作用1Alt P浏览器图片下载&#xff08;来自油猴脚本&#xff09; 二、其他功能 1、解决端口占用 第一步&…

Linux安装单细胞分析软件copykat

Linux安装单细胞分析软件copykat 测试环境 Linux centos 7R 4.1.2minconda3天意云24C192GB安装步骤 新建环境 conda activate copykatconda install r-base4.1.2 安装基础软件 checkPkg <- function(pkg){return(requireNamespace(pkg, quietly TRUE))}if(!checkPkg("…

类的加载过程-过程二:Linking阶段

链接过程之验证阶段(Verification) 当类加载到系统后&#xff0c;就开始链接操作&#xff0c;验证是链接操作的第一步。 它的目的是保证加载的字节码是合法、合理并符合规范的。 验证的步骤比较复杂&#xff0c;实际要验证的项目也很繁多&#xff0c;大体上Java虚拟机需要做…

基于stable diffusion的艺术操作

下面是作者基于stable diffusion的艺术操作 得益于人工智能的强大技术 以下所有的图 绝对是整体星球上唯一的图 现在人工智能越来越强大&#xff0c;感觉将来最有可能取代的就是摄影师、中低级的程序员、UI设计师、数据分析师等&#xff0c;人们未来更多从事的职业应该是快速…

机器学习 01

目录 一、机器学习 二、机器学习工作流程 2.1 获取数据 2.2 数据集 2.2.1 数据类型构成 2.2.2 数据分割 2.3 数据基本处理 2.4 特征工程 2.4.1什么是特征工程 2.4.2 为什么需要特征工程(Feature Engineering) 2.4.3 特征工程内容 2.5 机器学习 2.6 模型评估 2.7 …

【消息队列】细说Kafka消费者的分区分配和重平衡

消费方式 我们直到在性能设计中异步模式&#xff0c;一般要么是采用pull&#xff0c;要么采用push。而两种方式各有优缺点。 pull &#xff1a;说白了就是通过消费端进行主动拉去数据&#xff0c;会根据自身系统处理能力去获取消息&#xff0c;上有Broker系统无需关注消费端的…

Windows GPU版本的深度学习环境安装

本文记录了cuda、cuDNN的安装配置。 参考文章&#xff1a; cuda-installation-guide-microsoft-windows 12.1 documentation Installation Guide :: NVIDIA cuDNN Documentation 一、cuda安装 注意事项&#xff1a; 1、cuda安装最重要的是查看自己应该安装的版本。 表格…

Java数组打印的几种方式

&#x1f389;&#x1f389;&#x1f389;点进来你就是我的人了 博主主页&#xff1a;&#x1f648;&#x1f648;&#x1f648;戳一戳,欢迎大佬指点!人生格言&#xff1a;当你的才华撑不起你的野心的时候,你就应该静下心来学习! 欢迎志同道合的朋友一起加油喔&#x1f9be;&am…

独立看门狗(IWDG)实验

独立看门狗简介 单片机系统在外界的干扰下会出现程序跑飞的现象导致出现死循环&#xff0c; 看门狗电路就是为了避免这种情况的发生 。IWDG&#xff08;Independent watchdog&#xff09;独立看门狗&#xff0c;可以用来检测并解决由于软件错误导致的故障&#xff0c;当计数器…

使用 ArcGIS Pro 进行土地利用分类的机器学习和深度学习

随着技术进步&#xff0c;尤其是地理信息系统 (GIS)工具的进步&#xff0c;可以更有效地对土地利用进行分类。分类的使用可用于识别植被覆盖变化、非法采矿区和植被抑制区域&#xff0c;这些只是土地利用分类的众多示例中的一部分。 分类的一大困难是确定要解决的问题的级别。…