文章目录
无监督学习(第三课第一周)
在无监督学习中,数据只有X,没有标签或者目标。
一、k-means算法
(一)k-means的算法执行过程
其中的k表示我们要找到个数据中簇的个数,这个由我们自己来设定。
以以上示例,分析整个K-means聚类算法的程序执行过程:
1、随机选择两个数据点,作为两个不同簇的中心;
2、遍历每个点,看它是更接近第一个簇中心还是第二个,将每个点分配到离它更近的簇质心(中心);
3、查看两个簇中所有数据点,并取平均值;将簇中心移动到该簇的平均位置;
4、重复执行2、3,直到簇中心的位置不再发生改变,表示聚类结束,k-means算法已经收敛。
下图就是上面步骤的一个描述:
注意:如果在执行过程中有一个簇中没有任何点分配给这个簇,我们通常的做法是删除这个簇,只剩下k-1个簇;或者是重新初始化簇中心。
当X是两个特征值向量时,为每个样本点分配最近的簇中心的相关代码如下:
# UNQ_C1
# GRADED FUNCTION: find_closest_centroids
def find_closest_centroids(X, centroids):
"""
Computes the centroid memberships for every example
Args:
X (ndarray): (m, n) Input values
centroids (ndarray): k centroids
Returns:
idx (array_like): (m,) closest centroids
"""
# Set K
K = centroids.shape[0]
# You need to return the following variables correctly
idx = np.zeros(X.shape[0], dtype=int)
### START CODE HERE ###
for i in range(X.shape[0]):
distance = []
for j in range(K):
temp = np.linalg.norm(X[i]-centroids[j])
distance.append(temp)
idx[i]=np.argmin(distance)
### END CODE HERE ###
return idx
计算质心的相关代码如下:
# UNQ_C2
# GRADED FUNCTION: compute_centpods
def compute_centroids(X, idx, K):
"""
Returns the new centroids by computing the means of the
data points assigned to each centroid.
Args:
X (ndarray): (m, n) Data points
idx (ndarray): (m,) Array containing index of closest centroid for each
example in X. Concretely, idx[i] contains the index of
the centroid closest to example i
K (int): number of centroids
Returns:
centroids (ndarray): (K, n) New centroids computed
"""
# Useful variables
m, n = X.shape
# You need to return the following variables correctly
centroids = np.zeros((K, n))
### START CODE HERE ###
for i in range(K):
temp = X[idx==i] # 寻找分配给该簇的所有样本点
# 下面是计算质心,我们可以通过循环进行计算也可以通过函数来np.means(temp,axios=0)计算
for j in range(n):
centroids[i][j] = sum(temp[:,j])/temp.shape[0]
### END CODE HERE ##
return centroids
(二)k-means的成本函数
**具体来说,k-means法的执行过程就是找到样本与该样本分配到的簇的簇中心距离的最小值。**这个成本函数也叫做失真函数。
当成本函数的值保持不变时,意味着K-means算法已经收敛。
(三)初始化聚类中心
不同的初始化方式可能会导致算法进入局部最小值,但此时的聚类结果并不是最好的。为了解决这个问题,我们常见的方式是多次运行k-means(多次初始化),尝试找到最好的。选择多次运行结果中代价函数最小的作为解决方案。
示例如下:
(四)如何决定簇的个数
一种选择聚类数量的方法叫做ELBO方法:通俗来讲就是选择不同的K值,看k-means算法收敛之后的成本函数的变化趋势,成本函数在变化工程中逐渐减小,到了那个成本函数的减小速度变慢的时候,那个k值就作为我们的目标k值。示例如下:
ELBO方法有一个坏处就是,当我们成本函数随着k值平滑地变化时,选择哪一个k值就变得很模糊,这样往往就会选择较大的k值,但是拥有较大的k值得成本函数总是会小一些,这种方法不是一个好方法。
通常的做法是根据你要解决的问题并且考虑成本对k值进行抉择,选择几个比较合适你任务的k值进行比较,在成本和效益之间做选择。
二、异常检测
通俗来讲,异常检测就是看我们的新数据与旧数据有没有相似的地方,有没有异常的地方。
常见的一种异常检测方法叫做密度估计。
(一)密度估计
如上所示,通过建立样本的概率模型,通过这个概率模型来评估新数据的概率,如果它小于某一阈值,则标记为异常,否则正常。
(二)高斯分布
建立概率模型,我们常常使用到高斯分布,也叫做正态分布。
高斯分布的公式及函数图像如上所示。
选择不同的均值和标准差,如何影响高斯分布,示例如下:
接着,我们就可以通过计算样本的均值和标准差来得出关于样本的概率函数,并且对新样本的概率进行估计。
上述是高斯分布在x是单个数值时的工作原理,如果我们的x是一个向量呢?
(三)将高斯分布应用到多个特征的异常检测算法中去
当数据具有多个数值特征值时,应该如何建立概率模型呢?示例如下:
我们可以将上述理解成,对每一个特征都建立一个概率模型,将测试数据集中的特征依次输入给上述模型,概率相乘表示这个特征值等于相应数据时同时发生的概率,就得到了最终的概率。
具体步骤如下:
当数据有两个特征,均值和标准差计算代码如下:
# UNQ_C1
# GRADED FUNCTION: estimate_gaussian
def estimate_gaussian(X):
"""
Calculates mean and variance of all features
in the dataset
Args:
X (ndarray): (m, n) Data matrix
Returns:
mu (ndarray): (n,) Mean of all features
var (ndarray): (n,) Variance of all features
"""
m, n = X.shape
### START CODE HERE ###
mu = np.mean(X,axis=0)
var = np.var(X,axis=0)
### END CODE HERE ###
return mu, var
算法意味着,当测试数据中某一个特征值的概率小于某一个阈值,那么整体的概率就会变小,表示数据出现了异常。
示例如下:
(四)开发和评估异常检测系统
对于一些我们已知目标值的数据,我们常常可以进行数值估计来评估模型的优劣,并对模型做进一步的调整。示例如下:
训练集使用正常的数据,而交叉验证集和测试集我们可以使用一部分正常的数据,并且加入一部分异常的数据,观察模型是否能够正确地将异常数据找出来,并且将正常地数据识别为正常;这里我们常常需要调整阈值地大小,或者是增加或者删除特征值,以此来调整模型的准确度。
**在交叉验证集或者测试集上实际评估算法:**可以使用到之前讲过的评估参数对交叉验证集和测试集进行评估(精确率、召回率、F1分数),因为我们已知目标值。
根据各种指标调整阈值代码如下:
# UNQ_C2
# GRADED FUNCTION: select_threshold
def select_threshold(y_val, p_val):
"""
Finds the best threshold to use for selecting outliers
based on the results from a validation set (p_val)
and the ground truth (y_val)
Args:
y_val (ndarray): Ground truth on validation set
p_val (ndarray): Results on validation set
Returns:
epsilon (float): Threshold chosen
F1 (float): F1 score by choosing epsilon as threshold
"""
best_epsilon = 0
best_F1 = 0
F1 = 0
step_size = (max(p_val) - min(p_val)) / 1000
for epsilon in np.arange(min(p_val), max(p_val), step_size):
### START CODE HERE ###
prediction = (p_val < epsilon)
tp = sum((prediction==1)&(y_val==1))
fp = sum((prediction==1)&(y_val==0))
fn = sum((prediction==0)&(y_val==1))
pre = tp/(tp+fp)
recall = tp/(tp+fn)
F1 = (2*pre*recall)/(pre+recall)
### END CODE HERE ###
if F1 > best_F1:
best_F1 = F1
best_epsilon = epsilon
return best_epsilon, best_F1
(五)异常检测VS监督学习
当我们有一些正样本和大量负样本时,我们应该用异常检测还是监督学习呢?
我们只有少量的正样本时,异常检测比较适用,这部分正样本通常用来在交叉验证集和测试集进行测试和调试,因为任何算法都很难从少量的正样本中学习到异常是什么,而我们的异常检测是对正常的数据进行学习,建立概率模型,一旦有偏离正常情况的数据,就能够识别为异常;当我们有大量的正负样本时,监督学习比较适用。
以下是一些他们各自适用的领域:
异常检测:欺诈检测、制造业(发现一些全新的问题)、数据中的监控机器(黑客攻击),对于安全领域的问题也大多常用异常检测。
监督学习:垃圾邮件、制造业(识别已经出现过的故障)、天气预测、疾病分类。
(六)调整异常检测算法的特征的实用技巧
在监督学习中,如果特征选择不是很对,或者选择了一些与问题无关的额外特征,实际上是没有多大关系的,因为算法有监督信号,有足够的标签使算法能够识别哪些特征可以忽略,并且进行特征缩放,充分利用提供的特征。而异常检测使用的是无标签数据,它不不能够确定哪些标签重要,哪些不重要,所以仔细选择特征对于异常检测比监督学习更为重要。
1、首先我们可以将不是高斯分布的特征转变为接近高斯分布,示例如下,我们可以使用各种各样的方式将我们的特征转变成高斯分布:
在将你的特征转变成高斯分布之后,在进行测试的时候,记得要对你的测试数据也进行相应的转换。
2、基于异常样本,激发新特征的构造
当我们使用交叉验证集进行测试时,如果发现有异常数据模型并没有识别出来,我们可以对异常数据进行分析,看看能不能构造一个新的特征,异常数据在这个特征上偏大或者偏小,加入到我们的模型中去,让我们更能识别出异常的数据。
3、基于旧特征构造新的特征
示例如下:
对您有用的话点赞收藏哦!!!!