人工智能基础作业_UNIT4

K均值聚类

一种无监督学习算法。用来把一组数据点分成K个不同的簇。主要目的是最小化簇内平方误差和。对数据点需要找最近的簇,对簇需要求得对点距离的平均值,然后更新簇。

K均值聚类是生成式还是判别式方法?

生成式方法,因为它试图学习生成数据的概率分布,不断更新新数据。

KNN VS. K-means

KNN算法是监督式学习算法,用于分类和回归,K-means是无监督学习算法,用于聚类。

主成分分析

数据降维技术。将高维空间的主要数据映射到低维空间方便计算。

LDA VS. PCA

都是降维用的。但是LDA是监督学习算法,用来分类。PCA是无监督学习算法,用于数据探索和可视化。

奇异值分解(SVD)

将一个矩阵分解成3个矩阵乘积。用来图像压缩,自然语言处理。
A = UΣV^T。
其中,U 和 V 是正交矩阵,Σ 是对角矩阵

特征人脸方法(Eigenface)

将人脸图像投影到低维空间,提取出最有区分性的特征,再把测试人脸也投影,来测试人脸身份。

潜在语义分析 (LSA)

把语言提取成一些矩阵和特殊值,用来判断不同语言的相似度,用来检索和分类用的,有可能查重网站利用的就是这种技术。

期望最大化算法(EM)

用于求解包含隐变量的概率模型参数的最大似然估计。

K-means是最简单的EM算法?

不完全,他们都有迭代的E步和M步最大化期望,但是算法不一样,目标函数也不同。

编程实现EM算法

main:

import matplotlib.pyplot as plt

from generate_data import generate_data
from em_algorithm import EMAlgorithm


# 生成测试数据集
X = generate_data(n_samples=300)

# 设置模型参数
n_clusters = 3
max_iter = 100

# 创建 EM 算法实例
em_algo = EMAlgorithm(n_clusters=n_clusters, max_iter=max_iter)

# 运行 EM 算法
em_algo.fit(X)

# 显示聚类结果
plt.scatter(X[:, 0], X[:, 1], c=em_algo.labels_)
plt.show()

EMAlgorithm:

import numpy as np


class EMAlgorithm:
    def __init__(self, n_clusters, max_iter):
        """
        初始化 EM 算法。

        Parameters
        ----------
        n_clusters : int
            聚类数量。
        max_iter : int
            最大迭代次数。
        """
        self.n_clusters = n_clusters
        self.max_iter = max_iter
        self.labels_ = None
        self.mu_ = None
        self.sigma_ = None
        self.pi_ = None

    def _initialize_params(self, X):
        """
        初始化模型参数。

        Parameters
        ----------
        X : ndarray of shape (n_samples, n_features)
            数据集。
        """
        n_samples, n_features = X.shape

        # 初始化均值向量、协方差矩阵和权重系数
        self.mu_ = np.zeros((self.n_clusters, n_features))
        self.sigma_ = np.zeros((self.n_clusters, n_features, n_features))
        self.pi_ = np.ones(self.n_clusters) / self.n_clusters

        # 从数据集中随机选取数据点作为聚类中心
        indices = np.random.choice(n_samples, size=self.n_clusters, replace=False)
        self.mu_ = X[indices]

        # 初始化协方差矩阵
        for k in range(self.n_clusters):
            self.sigma_[k] = np.eye(n_features)

    def _e_step(self, X):
        """
        执行 E 步骤。

        Parameters
        ----------
        X : ndarray of shape (n_samples, n_features)
            数据集。

        Returns
        -------
        resp : ndarray of shape (n_samples, n_clusters)
            每个数据点属于每个聚类的概率。
        """
        n_samples = X.shape[0]
        resp = np.zeros((n_samples, self.n_clusters))

        for k in range(self.n_clusters):
            diff = X - self.mu_[k]
            exponent = np.sum(diff @ np.linalg.inv(self.sigma_[k]) * diff, axis=1)
            resp[:, k] = self.pi_[k] * np.exp(-0.5 * exponent)
        resp /= np.sum(resp, axis=1, keepdims=True)

        return resp

    def _m_step(self, X, resp):
        """
        执行 M 步骤。

        Parameters
        ----------
        X : ndarray of shape (n_samples, n_features)
            数据集。
        resp : ndarray of shape (n_samples, n_clusters)
            每个数据点属于每个聚类的概率。
        """
        n_samples = X.shape[0]
        n_features = X.shape[1]

        # 计算每个聚类的权重系数
        self.pi_ = np.sum(resp, axis=0) / n_samples

        # 计算每个聚类的均值向量
        for k in range(self.n_clusters):
            self.mu_[k] = np.sum(resp[:, k].reshape(-1, 1) * X, axis=0) / np.sum(resp[:, k])

    # ... 省略其他代码 ...

    def fit(self, X):
        """
        使用 EM 算法拟合模型。

        Parameters
        ----------
        X : ndarray of shape (n_samples, n_features)
            数据集。
        """
        self._initialize_params(X)

        for i in range(self.max_iter):
            resp = self._e_step(X)
            self._m_step(X, resp)

            # 计算对数似然函数值
            ll = self._log_likelihood(X)
            print(f"Iteration {i+1}/{self.max_iter}: log-likelihood = {ll}")

        # 预测数据点属于哪个聚类
        self.labels_ = np.argmax(self._e_step(X), axis=1)

    def _log_likelihood(self, X):
        """
        计算对数似然函数值。

        Parameters
        ----------
        X : ndarray of shape (n_samples, n_features)
            数据集。

        Returns
        -------
        ll : float
            对数似然函数值。
        """
        n_samples = X.shape[0]
        ll = 0

        for k in range(self.n_clusters):
            diff = X - self.mu_[k]
            exponent = np.sum(diff @ np.linalg.inv(self.sigma_[k]) * diff, axis=1)
            ll += np.sum(np.log(self.pi_[k]) - 0.5 * np.log(np.linalg.det(self.sigma_[k])) - 0.5 * exponent)

        return ll / n_samples

Gmm:

import numpy as np
from scipy.stats import multivariate_normal


class GaussianMixtureModel:
    def __init__(self, k, max_iter=100, tol=1e-4):
        """
        初始化高斯混合模型。

        Parameters
        ----------
        k : int
            聚类数。
        max_iter : int, optional
            最大迭代次数,默认为 100。
        tol : float, optional
            收敛阈值,默认为 1e-4。
        """
        self.k = k
        self.max_iter = max_iter
        self.tol = tol

    def fit(self, X):
        """
        对数据集进行参数估计。

        Parameters
        ----------
        X : ndarray of shape (n_samples, n_features)
            数据集。

        Returns
        -------
        self
        """
        n_samples, n_features = X.shape

        # 初始化模型参数
        self.pi = np.ones(self.k) / self.k
        self.mu = X[np.random.choice(n_samples, self.k, replace=False)]
        self.sigma = np.array([np.eye(n_features)] * self.k)

        # 迭代更新模型参数
        for i in range(self.max_iter):
            # E 步:计算后验概率
            gamma = np.zeros((n_samples, self.k))
            for j in range(self.k):
                gamma[:, j] = self.pi[j] * multivariate_normal.pdf(X, mean=self.mu[j], cov=self.sigma[j])
            gamma /= gamma.sum(axis=1, keepdims=True)

            # M 步:更新模型参数
            pi_prev = self.pi.copy()
            mu_prev = self.mu.copy()
            sigma_prev = self.sigma.copy()
            self.pi = gamma.mean(axis=0)
            self.mu = gamma.T.dot(X) / gamma.sum(axis=0, keepdims=True).T
            for j in range(self.k):
                X_centered = X - self.mu[j]
                self.sigma[j] = (X_centered.T * gamma[:, j]).dot(X_centered) / gamma[:, j].sum()

            # 判断是否收敛
            pi_diff = np.abs(self.pi - pi_prev).max()
            mu_diff = np.abs(self.mu - mu_prev).max()
            sigma_diff = np.abs(self.sigma - sigma_prev).max()
            if pi_diff < self.tol and mu_diff < self.tol and sigma_diff < self.tol:
                break

        return self

    def predict(self, X):
        """
        对数据集进行预测。

        Parameters
        ----------
        X : ndarray of shape (n_samples, n_features)
            数据集。

        Returns
        -------
        labels : ndarray of shape (n_samples,)
            预测标签。
        """
        n_samples = X.shape[0]

        # 计算后验概率
        gamma = np.zeros((n_samples, self.k))

generate_data:

import numpy as np


def generate_data(n_samples):
    """
    生成测试数据集。

    Parameters
    ----------
    n_samples : int
        数据点数量。

    Returns
    -------
    X : ndarray of shape (n_samples, 2)
        数据集。
    """
    np.random.seed(0)

    # 生成高斯分布
    mu1 = [0, 0]
    sigma1 = [[1, 0], [0, 1]]
    mu2 = [3, 3]
    sigma2 = [[1, 0], [0, 1]]
    mu3 = [0, 3]
    sigma3 = [[1, 0], [0, 1]]
    X1 = np.random.multivariate_normal(mu1, sigma1, n_samples // 3)
    X2 = np.random.multivariate_normal(mu2, sigma2, n_samples // 3)
    X3 = np.random.multivariate_normal(mu3, sigma3, n_samples // 3)
    X = np.concatenate([X1, X2, X3])

    # 打乱数据集的顺序
    np.random.shuffle(X)

    return X

运行结果如下:
这是运行代码后的结果
代码当然不是我写的,只是为了体会算法模型的实现,我还没有成长到这一步,呜呜。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值