《机器学习》之《半监督学习》作业

《机器学习》之《半监督学习》作业

《机器学习》之《半监督学习》作业

题目1

从网上下载或自己编程实现TSVM算法 选择两个UCI数据集,将其中30%的样例用作测试样本,10%的样例用作有标记样本,60%的样例用作无标记样本。分别训练出利用无标记样本的TSVM以及仅利用有标记样本的SVM,并比较其性能。

解:
选择最常用的iris数据集,将数据集标准化之后,将其中30个样例用作测试样本,10个样例用作有标记样本,60个样例用作无标记样本。以sklearn的SVM算法为基础建立TSVM。模型训练好后,输出经过有标记的样本训练后对未标记样本的预测正确率、经过TSVM训练后,对未标记样本的预测正确率和经过TSVM训练后对测试样本的预测正确率。最后绘制散点图和分别由SVM和TSVM得到的超平面。代码如下:

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from sklearn import svm
from sklearn.datasets import load_iris
from sklearn.preprocessing import MinMaxScaler


def create_data():
    iris = load_iris()
    df = pd.DataFrame(iris.data, columns=iris.feature_names)
    df['label'] = iris.target
    df.columns = ['sepal length', 'sepal width', 'petal length', 'petal width', 'label']
    data = np.array(df.iloc[:100, [0, 1, -1]])
    # 对数据进行标准化处理
    sc = MinMaxScaler()
    sc.fit(data)
    data = sc.transform(data)
    data[:, -1] = data[:, -1] * 2 - 1
    # 30个测试样本
    test = np.vstack((data[:15], data[50:65]))
    # 10个有标记样本
    labeled_sample = np.vstack((data[15:20], data[65:70]))
    # 60个无标记样本
    unlabeled_sample = np.vstack((data[20:50], data[70:]))
    return test, labeled_sample, unlabeled_sample


test, labeled, unlabeled = create_data()
clf = svm.SVC(C=1, kernel='linear')
# 有标记的样本训练SVM
clf.fit(labeled[:, :2], labeled[:, -1])
positive_labeled = labeled[5:]
negative_labeled = labeled[:5]
plt.scatter(labeled[:5, :2][:, 0], labeled[:5, :2][:, 1], color='red', s=40, label=-1)
plt.scatter(labeled[5:, :2][:, 0], labeled[5:, :2][:, 1], color='blue', s=40, label=1)
x_points = np.linspace(0, 1, 10)
y_points = -(clf.coef_[0][0] * x_points + clf.intercept_) / clf.coef_[0][1]
plt.plot(x_points, y_points, color='green')
plt.legend()
# 伪标记
fake_label = clf.predict(unlabeled[:, :2])
unlabeled_positive_x = []
unlabeled_positive_y = []
unlabeled_negative_x = []
unlabeled_negative_y = []
for i in range(len(unlabeled)):
    if int(fake_label[i]) == 1:
        unlabeled_positive_x.append(unlabeled[i, 0])
        unlabeled_positive_y.append(unlabeled[i, 1])
    else:
        unlabeled_negative_x.append(unlabeled[i, 0])
        unlabeled_negative_y.append(unlabeled[i, 1])

plt.scatter(unlabeled_positive_x, unlabeled_positive_y, color='red', s=15)
plt.scatter(unlabeled_negative_x, unlabeled_negative_y, color='blue', s=15)
print('经过有标记的样本训练后,对未标记样本的预测正确率为{}'.format(clf.score(unlabeled[:, :2], unlabeled[:, -1])))

Cu = 0.1
Cl = 1  # 初始化Cu,Cl
weight = np.ones(len(labeled) + len(unlabeled))
# 样本权重
weight[len(unlabeled):] = Cu
# 用于训练有标记与无标记样本集合
train_sample = np.vstack((labeled[:, :2], unlabeled[:, :2]))
# 用于训练的标记集合
train_label = np.hstack((labeled[:, -1], fake_label))
unlabeled_id = np.arange(len(unlabeled))

while Cu < Cl:
    clf.fit(train_sample, train_label, sample_weight=weight)
    while True:
        # 通过训练得到的预测标记
        predicted_y = clf.decision_function(unlabeled[:, :2])
        # 伪标记,这里为与预测的区分开,写为real_y
        real_y = fake_label
        epsilon = 1 - predicted_y * real_y
        positive_set, positive_id = epsilon[real_y > 0], unlabeled_id[real_y > 0]
        negative_set, negative_id = epsilon[real_y < 0], unlabeled_id[real_y < 0]
        positive_max_id = positive_id[np.argmax(positive_set)]
        negative_max_id = negative_id[np.argmax(negative_set)]
        epsilon1, epsilon2 = epsilon[positive_max_id], epsilon[negative_max_id]
        if epsilon1 > 0 and epsilon2 > 0 and round(epsilon1 + epsilon2, 3) >= 2:
            fake_label[positive_max_id] = -fake_label[positive_max_id]
            fake_label[negative_max_id] = -fake_label[negative_max_id]
            train_label = np.hstack((labeled[:, -1], fake_label))
            clf.fit(train_sample, train_label, sample_weight=weight)
        else:
            break
    # 更新Cu
    Cu = min(2 * Cu, Cl)
    # 更新样本权重
    weight[len(unlabeled):] = Cu
# 绘图
x_points = np.linspace(0, 1, 10)
y_points = -(clf.coef_[0][0] * x_points + clf.intercept_) / clf.coef_[0][1]
plt.plot(x_points, y_points, color='yellow')
plt.savefig('运行结果.jpg')
plt.show()
# 打印结果
print('经过TSVM训练后,对未标记样本的预测正确率为{}'.format(clf.score(unlabeled[:, :2], unlabeled[:, -1])))
print('经过TSVM训练后,对测试样本的预测正确率为{}'.format(clf.score(test[:, :2], test[:, -1])))

运行程序后,我们得到:经过有标记的样本训练后,对未标记样本的预测正确率为0.9666666666666667,经过TSVM训练后,对未标记样本的预测正确率为0.9833333333333333,经过TSVM训练后,对测试样本的预测正确率为1.0。

在这里插入图片描述

图1 散点图与超平面

程序绘制的散点图和超平面如图1所示。其中,绿线是仅利用有标记样本的SVM得到的超平面,黄线是利用无标记样本的TSVM模型得到的超平面。
由实验结果可知,对于iris数据集,TSVM通过利用未标记数据能提高最终分类的准确率,从SVM的96.67%提高到了TSVM的98.33%,并且预测标记与测试集的真实标记一致,预测正确率为100%。

题目2

假设数据由混合专家(mixture of experts)模型生成,即数据是基于k个成分混合而得的概率密度生成: p ( x │ θ ) = ∑ ( i = 1 ) k [ α i ⋅ p ( x │ θ i ) ] p(x│θ)=∑_(i=1)^k[α_i·p(x│θ_i ) ] p(xθ)=(i=1)k[αip(xθi)],其中, θ = θ 1 , θ 2 , … , θ k θ={θ_1,θ_2,…,θ_k} θ=θ1,θ2,,θk是模型参数, p ( x │ θ i ) p(x│θ_i ) p(xθi)是第 i i i个混合成分的概率密度,混合系数 α i ≥ 0 , ∑ ( i = 1 ) k [ α i = 1 ] α_i≥0,∑_(i=1)^k[α_i=1] αi0(i=1)k[αi=1]。假设每个混合成分对应一个类别,但每个类别可能包含多个混合成分。试推导相应的生成式半监督学习算法。

解答:机器学习-周志华-个人练习13.3

03-08
### Transductive Support Vector Machine (TSVM) 实现与应用 #### TSVM简介 转导支持向量机(TSVM)由Vladimir N. Vapnik在1998年引入[^1]。不同于传统的归纳学习方法,TSVM旨在直接针对特定测试集进行优化而不是构建泛化的分类器。 #### TSVM实现原理 TSVM的核心思想是在标准的支持向量机框架基础上增加对未标记数据的学习能力。具体来说,TSVM不仅考虑已知标签的数据点,还会利用大量无标签数据来指导超平面的选择。这样做可以使得最终形成的决策边界更加贴近实际分布情况,从而提高分类效果。 对于半监督场景下的SVM改进版本——即TSVM算法而言,在原有SVM的基础上加入了一种机制用来估计未知样本$\hat{y}$ 的标签,并且巧妙地把惩罚系数纳入到了迭代更新过程中作为可调参数处理[^2]。 以下是基于Python的一个简单TSVM实现案例: ```python from sklearn.semi_supervised import LabelSpreading import numpy as np def transductive_svm(X_labeled, y_labeled, X_unlabeled): """ 使用Label Spreading 方法模拟TSVM 参数: X_labeled : array-like of shape (n_samples, n_features) 已标注训练集特征矩阵. y_labeled : array-like of shape (n_samples,) 对应于X_labeled的标签数组 X_unlabeled : array-like of shape (m_samples, n_features) 未标注数据集特征矩阵 返回值: labels_pred : ndarray of shape (m_samples,) 预测出来的未标注数据对应的标签 """ # 合并有标签和无标签的数据 X_all = np.vstack((X_labeled, X_unlabeled)) # 初始化label spreading模型 label_spread_model = LabelSpreading(kernel='knn', alpha=0.7) # 创建完整的标签列表,其中未标注项设为-1表示缺失 combined_labels = np.hstack([y_labeled, [-1]*len(X_unlabeled)]) # 训练模型 label_spread_model.fit(X_all, combined_labels) # 获取所有实例的新标签分配 all_labels = label_spread_model.transduction_ # 只返回原先未标注部分的结果 labels_pred = all_labels[len(y_labeled):] return labels_pred ``` 此代码片段展示了如何使用`sklearn`库中的`LabelSpreading`类近似实现TSVM的功能。该方法本质上是一种图正则化技术,它允许信息在网络节点间传播直到达到稳定状态为止。这里采用KNN核函数以及设置平滑度参数alpha等于0.7来进行实验配置。 #### 应用领域 TSVM特别适合应用于那些难以获得充分标注样本的任务中,比如医学影像分析、自然语言处理等领域内的细粒度分类问题。由于其能够在少量甚至完全没有人工干预的情况下有效挖掘潜在模式,因此具有广泛的应用前景。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

UestcXiye

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

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

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

打赏作者

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

抵扣说明:

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

余额充值