聚类分析7—多元回归树(MRT):约束聚类(数量生态学:R语言的应用 第四章

数量生态学:R语言的应用 第四章 聚类分析7—多元回归树(MRT):约束聚类

聚类分析的内容是不是很多,不要慌,马上就快结束了,这次讲的是多元回归树(MRT):约束聚类

1. 概述:多元回归树

多元回归树(MRT)是一元回归树的拓展。一元回归树是在定量或分类解释变量的控制下递归划分一个定量变量。该分类方式有时也称为约束聚类或导向聚类

输出结果是树状图,树的叶子(样方的最终分组)通过最小化组内平方和确定(类似k-均值划分),但每次划分的分割点取自解释变量,而非被划分的数据。在大量可能的分类结果中(叶的数量和组成),通常保留具有最大预测能力的回归树

注意:之后第6章学习约束排序中,选择解释变量是依照解释能力大小,而MRT选择解释变量是侧重预测能力大小,这使MRT在环境管理等实际应用中非常有用。

MRT是一种强大而可靠的分类方法,即使被划分的变量缺少某些值,或响应变量和解释变量是非线性关系,或解释变量之间存在高阶相互关系,MRT都可以使用。

2.计算(原理)

MRT的计算由两个一起运行的程序组成:

①数据约束划分

②分组结果交叉验证。

那它们是如何一起工作产生决定树形式的模型呢?

2.1 数据约束划分

  1. 对于每一个解释变量,将样方分为所有可能的两组情况。对于一个定量的解释变量,按照变量值大小先对样方进行排列,然后在第1个、第2个……第(n-1)个间隔点将样方划分为n-1种可能的两组分组情况。
  2. 对于分类变量,将变量所有水平随机组合成所有可能的两组,在每种情况下,样方也跟随变量水平的组合分为两组。对于所有的情况,计算两组内每个响应变量的值与该组平均值的距离平方和(组内SS),选择最小距离平方和的分组情况,并确认此分组情况所对应的解释变量的分割点或分类变量的水平组合
  3. 对于已分类的两个样方亚组,根据上面的步骤再继续将每个亚组一分为二,对于每个亚组,同样保留最小距离平方和所对应的解释变量分割点或分类变量的水平组合。
  4. 继续分割直到每个对象成为独立一组为止。一般情况下,我们不需要最大的树(即每片叶子只有一个对象),只需要大小(组数)合适的树。如何确定大小合适的树,可以使用确定最佳回归树的方法:交叉验证(cross-validation)。
  5. 除了树叶的数量和组成,相对误差(RE)也是回归树的主要特征,即所有叶子的组内SS(离差平方和)的和除以原始数据SS。换句话说,相对误差是回归树不能解释的方差比例。如果没有交叉验证,我们应该保留最小RE的回归树,即保留最高R²的回归树。然而,R²最高的回归树解释能力最好,不代表预测能力最好。注意:“用RE衡量回归树预测新数据的准确性过分乐观,而利用交叉验证相对误差(CVRE)估计预测值的准确性更好。”

2.2 交叉验证和回归树的裁剪

该如何对回归树进行裁剪(即保留最佳分类方案)?

如果从预测的角度解决这个问题,可以利用原始数据的一部分(称为“训练组”)构建一棵树,剩下另一部分(称为“验证组”)验证训练组构建的树的预测准确性,通过将验证组直接分配给训练组构建的树来实现。好的预测树总是会正确分配新对象,即新分配的响应变量总是接近所在组的形心。可以通过预测误差评估回归树的预测能力

预测误差的测度称为CVRE,函数表达式为:
CVRE= \displaystyle{\frac{\sum_{i=1}^{v}\sum_{i=1}^{n}\sum_{j=1}^{p}({y_{ij(k)}-\hat{y}}_{(k)})^2}{\sum_{i=1}^{n}\sum_{j=1}^{p}({y_{ij}-\overline{y}}_{j})^2}}
式中,y_{ij(k)}是验证组k中的每个观测值,\hat{y}_{(k)}是验证组k中每个观测值(即分类组的形心),分母代表验证组响应变量的总体离差平方和。

CVRE 可以定义为验证组未能被树解释的方差除以验证组总方差。当然,上述公式中的分子会随着分组情况的变化而改变。CVRE 为0是最完美的预测,接近1是最差的预测

2.3 MRT运算流程

MRT运算是两个模块同时运行,接下来将这两个模块放在一起,解释MRT交叉验证的运算过程:

  • 随机将数据分为k组(默认k=10)。
  • 从k组中取出1组作为验证组,剩余k-1组重新混合通过约束划分建立回归树,分组原则是最小化组内SS。
  • 重复上面的步骤k-1次,即依次剔除1组数据。
  • 共可以产生k个回归树,对于每个回归树的不同分类水平,将验证组(1组数据)内的对象分配到分组结果中。计算每个回归树不同分类水平的CVRE。公式只是每个回归树一种分类水平的CVRE的算法。·
  • 裁剪回归树:保留具有最小CVRE的回归树。另一个替代方案是,保留CVRE的值在最小CVRE+1个标准误范围内最小的分类水平。这个方法也称作“1SE”准则。
  • 为了获得上面的运行过程的误差估计值,需要多次(100次或500次)重复将对象随机分配为k组。
  • 置换检验保留具有最小CVRE值(更常用是1SE规则)的回归树。
  • 在mvpart函数中,当参数minauto=TRUE时,一组中最少可能的对象数等于ceiling(1og2(n))。如果设置minauto=FALSE允许分区继续进行,最终的分组方案可以由用户自己选择。
  • 在MRT分析中,平方和的计算具有欧氏空间属性。考虑到某些数据的特殊性,在输入程序之前,可能需要预先转化,比如:物种数据的欧氏距离转化。如果响应变量是具有不同量纲的环境因子,在运行MRT之前需要进行标准化。

3.使用mvpart和MVPARTwrap程序包运行MRT

3.1 安装最新版本mvpart包

通过以下代码来安装mvpart和MVPARTwrap程序包,因为R官方不支持

install.packages("devtools")
library(devtools)
install_github("cran/mvpart",force=TRUE)
install_github("cran/MVPARTwrap",force=TRUE)
library(mvpart)
library(MVPARTwrap)

mvpart包也包括一元回归树的函数rpart()。回归树函数所需数据要求响应变量的数据类型为矩阵,解释变量为数据框。函数内表达式与回归函数(见?lm)类似。

3.2 加载数据和包及数据预处理

setwd("E:/Rstudio_working/lai jian shan/DATA/Data")
install.packages("devtools")
library(devtools)
install_github("cran/mvpart",force=TRUE)
install_github("cran/MVPARTwrap",force=TRUE)
library(mvpart)
library(MVPARTwrap)
library(vegan)

#导入Doubs数据
load("Doubs.RData")
#剔除无物种数据的样方8
spe <- spe[-8,]
env <- env[-8,]
spa <- spa[-8,]
latlong <- latlong[-8,] #经纬度
##1.2 数据预处理#####
#先计算样方之间的弦距离矩阵
spe.norm <- decostand(spe,"normalize")
spe.ch <- vegdist(spe.norm,"euc")

# 计算Ward最小方差聚类
spe.ch.ward <- hclust(spe.ch, method="ward.D2")

#Ward聚类同表型相关
spe.ch.ward.coph <- cophenetic(spe.ch.ward)
cor(spe.ch, spe.ch.ward.coph)

# 设定聚类组的数量
k <- 4  
# 根据上面4个融合水平值图,可以观察到分4组水平在所有图里有小的跳跃
# 裁剪聚类树

spech.ward.g <- cutree(spe.ch.ward, k=k)

# 计算Ward聚类获得4组中各个物种的平均多度矩阵
groups <- as.factor(spech.ward.g)
spe.means <- matrix(0, ncol(spe), length(levels(groups)))
row.names(spe.means) <- colnames(spe)
for (i in 1:ncol(spe)) {
  spe.means[i, ] <- tapply(spe.norm[, i], spech.ward.g, mean)
}
# 平均物种多度矩阵作为初始点
startpoints <- t(spe.means)
# 基于初始点的k-均值划分
spe.kmeans2 <- kmeans(spe.norm, centers = startpoints)

# 最终分组的轮廓宽度值图
spech.ward.gk <- spe.kmeans2$cluster

3.3 最简单的MRT的应用,解释变量是Doubs数据集所有的解释变量

下面是最简单的MRT的应用,解释变量是Doubs数据集所有的解释变量。

这里需要生成一个被解释变量约束的鱼类数据多元回归树,首先要将每个样方鱼类数据进行弦转化,所以后面所算的距离也是弦距离。

在函数mvpart()的参数中,使用xvar1=29交叉验证组(即等于样方数,而不是常用的10组),100次的选代,这里允许通过人机交互方式从函数mvpart()提供的误差图中选择分类方案(下图左图)。误差图显示相对误差RE,一般会随着分类组数的增加而稳定减少。而CVRE通常先急剧减少,达到最小值后再增加,表明存在预测能力最佳的分组数,当数据分的组越多,预测质量越低。

当前生成的图是带1个最小CVRE的标准误的误差条形图,红色的水平线指示最小CVRE(大红点)的1个标准差范围
我们可以选择具有最好预测能力的树;如果按照一元回归树设定的原则:选择在1个最小CVRE的标准误范围内分组最少的分类树。在这里,k=2即可以达到的标准。分两组的回归树很简洁,预测能力仅仅稍逊色于最佳的预测树(最小CVRE)。

dev.new(
  title = "多元回归树-所有解释变量",
  width = 14,
  height = 7,
  noRStudioGD = TRUE
)
par(mfrow = c(1, 2))
#尝试的选择分为4组回归树结果。
spe.ch.mvpart <-
  mvpart(
    data.matrix(spe.norm) ~ .,
    env,
    margin = 0.08,
    cp = 0,
    xv = "pick",
    xval = nrow(spe),
    xvmult = 100,
    which=4
  )

# 注意参数xv="pick",必须点击鼠标左键,才会生成一个回归树,不然无法停止
summary(spe.ch.mvpart)
printcp(spe.ch.mvpart)

image-20210512200600734
  • 左图:相对误差RE(稳定减少)和交叉验证相对误差CVRE图。图中红点位置表示具有最小CVRE的分类方案,以及CVRE的误差线,上方绿色的条形指出获得最佳分类方案交又验证迭代的次数。
  • 右图:被环境变量解释的Doubs鱼类数据的多元回归树

参数xv="pick"允许通过人机交互的方式选择所需要的分类分组。如果自动选择具有最小CVRE值的回归树,可以设定xv="min"。

mvpart()函数产生的回归树除了底部显示一些常规的统计信息(误差,即1-R²、交叉验证的误差、标准误)外,还有其他信息。

下面这些回归树的特征非常重要:

  • 每个节点通过一个解释变量划分。例如第一个节点被海拔划分为含有13个和16个样方的两组。分割点(海拔341m)在原始数据中无此值,它是分割点左右两个样方海拔的平均值。
  • 每片叶子(终端)都显示所含样方的数量和RE,并显示该组内物种多度分布情况的小条形图(物种排列顺序按照响应变量矩阵内的列变量顺序排序)。为了比较不同组内物种差异,使用前面所讲的寻找特征种或指示种函数(见6指示物种)是一种更有统计意义的途径.
  • 对于一个新的观测(样方),可以根据其“相应”环境变量的值和回归树,将新样方直接分配到某一组。“相应”是指这里分配对象所需的变量可能因树的分支而异。样方不断分组过程中,一个环境变量可以多次使用。

下面代码除了可以查看残差,还能检索每个节点的不同对象并查看每个节点的特征:

#  MRT 的残差
dev.new(
  title = "MRT 的残差",
  width = 10,
  height = 6,
  noRStudioGD = TRUE
)
par(mfrow = c(1, 2))
hist(residuals(spe.ch.mvpart), col = "bisque")
plot(predict(spe.ch.mvpart, type = "matrix"),
     residuals(spe.ch.mvpart),
     main = "Residuals vs Predicted")
abline(h = 0, lty = 3, col = "grey")


image-20210512212513085
# 组的组成
spe.ch.mvpart$where
# 识别组的名称
(groups.mrt <- levels(as.factor(spe.ch.mvpart$where)))
# 第一片叶子鱼类的组成成分
spe.norm[which(spe.ch.mvpart$where == groups.mrt[1]), ]
# 第一片叶子的环境变量组成
env[which(spe.ch.mvpart$where == groups.mrt[1]), ]
image-20210512212735223
image-20210512212758207
image-20210512212811128

使用MRT结果来生成每组中鱼类组成的饼图

# 叶子的鱼类物种组成表格和饼图
leaf.sum <- matrix(0, length(groups.mrt), ncol(spe))
colnames(leaf.sum) <- colnames(spe)
for (i in 1:length(groups.mrt))
{
  leaf.sum[i, ] <-
    apply(spe.norm[which(spe.ch.mvpart$where == groups.mrt[i]), ],
          2, sum)
}
leaf.sum

dev.new(title = "使用MRT获得的4组中每组鱼类组成的饼", noRStudioGD = TRUE)
par(mfrow = c(2, 2))
for (i in 1:length(groups.mrt))
{
  pie(which(leaf.sum[i, ] > 0),
      radius = 1,
      main = paste("leaf #", groups.mrt[i]))
}


image-20210512213031143
使用MRT获得的4组中每组鱼类组成的饼

用MRT()函数分析mvpart()

# 从mvpart()函数获得的结果对象中提取MRT结果
# 必须加载MVPARTwrap和rdaTest程序包
spe.ch.mvpart.wrap <-
  MRT(spe.ch.mvpart, percent = 10, species = colnames(spe))
summary(spe.ch.mvpart.wrap)
image-20210512213721075
image-20210512213757848
image-20210512213829904
image-20210512213900776
image-20210512213944879

注意:参数percent设定每个节点(叶子)对该节点所承载的方差贡献率小于该比例值的物种不显示。这个值是任选的值,不需要统计检验。

MRT()函数运行结束后,屏幕上会直接显示回归树结果。这些结果以典范排序形式出现,因为MRT()函数实际上对物种进行RDA分析(解释变量同MRT分析)。在输出结果中,R²(等于1-RE)在上面的案例中,第一个图给出回归树的误差是0.37,因此这里输出的R²等于0.63。

  • 对MRT()函数的结果进行总结分析,可以显示每个节点承载的被解释总方差(也称“复杂性”)的比例。被解释总方差占数据原始总方差的比例即回归树的R²
  • MRT()函数也可以识别每个节点的判别物种,即对方差解释贡献最大的物种(贡献率小于用户设定参数percent值的物种不显示)。
  • MRT()函数也会提供每个节点两个分支的物种的平均多度,所以我们能够看到分支中哪个物种是判别物种。例如,案例分析表明,第一个节点左边分支(高海拔)的判别物种是Satr,Phph和Bab1三个物种,而右边分支的判别物种是Ala1。总结列表显示每片叶子的样方组成。

4. 组合MRT和IndVal

可以从MRT分类结果中寻找指示种,因为指示种可以进行指示值显著性检验(通过Holm法对多重检验的P值进行矫正),所以比单纯视觉判别特征种更好。

library(labdsv)
# 从MRT分类结果中寻找指示种
spe.ch.MRT.indval <- indval(spe.norm, spe.ch.mvpart$where)
pval.adj3 <- p.adjust(spe.ch.MRT.indval$pval)    # 矫正概率

image-20210512222839935

下面的图表明显著指示种对应的叶的编号和显著指示种所在组(叶)的指示值

# 为每个显著指示种对应叶的编号和显著指示种所在组(叶)的指示值
spe.ch.MRT.indval$maxcls[which(pval.adj3 <= 0.05)]
image-20210512223225443
# 每个显著的物种在最高指示值的叶子中的指示值
spe.ch.MRT.indval$indcls[which(pval.adj3 <= 0.05)]
image-20210512223359380

截图的内容表明,并非所有的组都有指示种,第4组(最右边)的指示种最多。从单个物种分析,褐蹲(Satr)是第一组(第一片叶)最显著的指示种(指示值为0.7900)。

比较MRT分组结果和Ward聚类的分组结果,首先必须把通过MRT获得不连续的组号变为连续的组号

# 展示从MRT获得的分组
spech.mvpart.g <- factor(spe.ch.mvpart$where)
levels(spech.mvpart.g) <- 1:length(levels(spech.mvpart.g))
# 比较MRT分组结果和Ward聚类的分组结果
table(spech.mvpart.g, spech.ward.g)
比较MRT分组结果和Ward聚类的分组结果
# 将MRT获得的分组结果在Doubs河流显示出来
dev.new(title = "Doubs河流显示将MRT获得的分组结果",
        width = 9,
        noRStudioGD = TRUE)
source("drawmap.R")#加载函数
drawmap(xy = spa,
        clusters = spech.mvpart.g,
        main = "Doubs河流显示将MRT获得的分组结果")
Doubs河流显示将MRT获得的分组结果

5.MRT作为单元聚类方法

单元聚类是一种非约束聚类,聚类过程选择单个响应变量进行作为分组的依据。在MRT运算过程中,如果响应变量和解释变量在同一个矩阵,就是单元聚类。这个过程就是不断利用不同指示物种的多度数值(或有一无数据)对样方进行分组。响应变量可以是有一无数据或是未转化的多度数据;解释变量可以是二元(有无)数据或者定量数据(转化或未转化均可)虽然响应变量和解释变量都是同一数据,但是响应变量和解释变量可以进行不同的转化。

对鱼类多度进行单元聚类分析:

#spe.pa 即是响应变量又是解释变量
spe.pa <- decostand(spe, "pa")

dev.new(
  title = "MRT for monothetic clustering",
  width = 14,
  height = 7,
  noRStudioGD = TRUE
)
par(mfrow = c(1, 2))

# spe.pa 即是响应变量又是解释变量
res.part1 <-
  mvpart(
    data.matrix(spe.pa) ~ .,
    data = spe.pa,
    margin = 0.08,
    xv = "p",
    xvmult = 100
  )
# 这里建议点击期望分组数(建议6组)
res.part1$where
基于MRT将鱼类有-无数据同时作为解释变量和响应变量的单元聚类方法
image-20210512230205087
# spe.norm 是响应变量, spe.pa 是解释变量
dev.new(
  title = "MRT for monothetic clustering",
  width = 14,
  height = 7,
  noRStudioGD = TRUE
)
par(mfrow = c(1, 2))
res.part2 <-
  mvpart(
    data.matrix(spe.norm) ~ .,
    data = spe.pa,
    margin = 0.08,
    xv = "p",
    xvmult = 100
  )
# 这里建议点击期望分组数(建议5组)
res.part2$where
image-20210512230454133
image-20210512230537164
# spe.norm 是响应变量, spe(未转换数据)是解释变量
dev.new(
  title = "MRT for monothetic clustering",
  width = 14,
  height = 7,
  noRStudioGD = TRUE
)
par(mfrow = c(1, 2))
res.part3 <-
  mvpart(
    data.matrix(spe.norm) ~ .,
    data = spe,
    margin = 0.08,
    xv = "p",
    cp = 0,
    xvmult = 100
  )
# 这里建议点击期望分组数(建议6组)
image-20210512230709805
# 每组成员-两边都是有-无数据
res.part1$where
res.part1.g <- factor(res.part1$where)
levels(res.part1.g) <- 1:length(levels(res.part1.g))

# 与非约束聚类进行比较
table(res.part1.g, spech.ward.g)
table(res.part1.g, spech.ward.gk)
image-20210512231335122
# 基于MRT鱼类数据单元聚类分析
source("drawmap3.R")
dev.new(title = "在Doubs河流展示基于MRT单元聚类获得的6组分",
        width = 9,
        noRStudioGD = TRUE)
drawmap3(xy = spa,
         clusters = res.part1.g,
         main = "在Doubs河流展示基于MRT单元聚类获得的6组分组")
在Doubs河流展示基于MRT单元聚类获得的6组分组

好了,这就是多元回归树(MRT)的全部内容了,概念有点多,数据理解可能也比较困难,还是多看多分析吧。加油,未来可期!

下一次将带来聚类分析的最后一部分内容—顺序聚类和模糊聚类,请期待。这些案例源代码都上传到我的gitee仓库,可到wx公众号回复:数量生态学即可获得仓库链接

如有不足或错误之处,请批评指正。
有什么不明白的也欢迎留言讨论。

欢迎关注同名微信公众号

往期内容:

《数量生态学:R语言的应用》第三章-R模式

《数量生态学:R语言的应用》第二版第三章-关联测度与矩阵------Q模式

《数量生态学:R语言的应用》第二版笔记2

《数量生态学——R语言的应用》第二版阅读笔记--绪论和第二章(一部分)

R语言 pheatmap 包绘制热图(基础部分)

R语言pheatmap包绘制热图进阶教程

使用PicGo和gitee搭建图床

组间分析—T检验、R语言绘图

Rmarkdown的xaringan包来制作PPT

htlm文件部署到个人网站

感谢你的阅读!!!你的点赞关注转发是对我最大的鼓励。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,230评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,261评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,089评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,542评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,542评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,544评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,922评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,578评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,816评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,576评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,658评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,359评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,937评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,920评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,859评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,381评论 2 342

推荐阅读更多精彩内容