实验二 - 线性判别分析

一、实验目的

1.复习线性判别分析相关原理和算法
2.使用函数库实现对两个二维数据集的线性判别分析
3.使用数值计算方法实现对两个二维数据集的线性判别分析(选做)

二、实验原理

线性判别分析是一种经典的线性学习方法,在二分类问题上最早由Fisher在1936年提出,亦称Fisher线性判别。线性判别的思想非常朴素:给定训练样例集,设法将样例投影到一条直线上,使得同类样例的投影点尽可能接近,异样样例的投影点尽可能远离;在对新样本进行分类时,将其投影到同样的直线上,再根据投影点的位置来确定新样本的类别。

三、实验代码

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.colors import ListedColormap #色彩设置
# 鸢尾花数据集
from sklearn.datasets import load_iris
# 导入线性判别分析函数
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis

# 导入鸢尾花数据集
dataset = load_iris()
# 显示数据形状
dataset.data.shape

x = dataset.data[:, : 2]  # 选前两个特征
y = dataset.target
target_names = dataset.target_names  # 获得标签名
colors = [ 'navy', 'turquoise', 'darkorange']  # 设置颜色

for color, i, target_name in zip(colors, [ 0, 1, 2], target_names):
    plt.scatter(x[y == i, 0], x[y == i, 1], color = color, label = target_name) 

plt.legend(loc= 'best', shadow= False, scatterpoints= 1) # 设置图例
plt.xlabel( "length") # 设置x轴备注
plt.ylabel( "width")  # 设置y轴备注
plt.show()

h= 0.02  # 绘制范围图的步数

# 定义LDA模型并训练
clf = LinearDiscriminantAnalysis()
clf.fit(x, y)  # LDA训练

# 绘制颜色地图
cmap_light = ListedColormap([ '#FFAAAA', '#AAFFAA', '#AAAAFF']) # 三种分类颜色的clour code
cmap_bold = ListedColormap([ '#FF0000', '#00FF00', '#0000FF'])  # 三种点的颜色
x_min, x_max = x[:, 0].min() - 1, x[:, 0].max() + 1   
y_min, y_max = x[:, 1].min() - 1, x[:, 1].max() + 1

# 将两个一维数组变成,间隔0.02的矩阵
xx, yy = np.meshgrid(np.arange(x_min, x_max, h), np.arange(y_min, y_max, h)) 
z = clf.predict(np.c_[xx.ravel(), yy.ravel()]) # 将xx,yy变成一维数组
z = z.reshape(xx.shape) 

plt.figure()
plt.pcolormesh(xx, yy, z, cmap = cmap_light)  # plt.pcolormesh()会根据y_predict的结果自动在cmap里选择颜色

# 绘制样本散点图
plt.scatter(x[:, 0], x[:, 1], c=y, cmap=cmap_bold, edgecolor= 'k', s= 20)
plt.xlim(xx.min(), xx.max())
plt.ylim(yy.min(), yy.max())
plt.title( "LDA iris")
plt.xlabel( "length") # 设置x轴备注
plt.ylabel( "width")  # 设置y轴备注

plt.show()

四、运行结果

运行结果

运行结果

五、思考题

1.叙述线性判别分析的实现过程。

(1)导入numpy、sklearn、matplotlib等相关的包;
(2)导入鸢尾花数据集
(3)划分变量x、y
(4)画散点图,显示数据集里面点的情况
(5)定义LDA模型并训练
(6)绘制样本散点图,显示结果

2.说明“LinearDiscriminantAnalysis”函数中各参数的意义。

LinearDiscriminantAnalysis函数的原型为:

class sklearn.discriminant_analysis.LinearDiscriminantAnalysis(solver='svd', shrinkage=None, priors=None, n_components=None, store_covariance=False, tol=0.0001, covariance_estimator=None)

函数中各参数的含义如下:
solver: 指定了求解最优化问题的算法,可以为svd奇异值分解、lsqr最小平方差或eigen特征分解算法,默认为svd。
shrinkage: 该参数通常在训练样本数量小于特征数量的场合下使用,可以为None(表示不使用)、auto或0~1之间的小数。默认为None。
priors: 一个数组,数组中的元素依次指定了每个类别的先验概率。如果为None,则认为每个类的先验概率都是等可能的。默认为None。
n_components: 一个整数。指定了数组降维后的维度(该值必须小于n_classes-1)。默认为None。
store_covariance: 一个布尔值。如果为True,则需要额外计算每个类别的协方差矩阵。默认为None。
tol: 一个浮点数。它指定了用于SVD算法中评判迭代收敛的阈值。默认为0.0001。
covariance_estimator: 协方差估计,默认为None,如果不是None,则用于估计协方差矩阵,而不是依赖经验协方差估计器(具有潜在的收缩)。

六、参考

scikit-learn 1.0.1

实验三 - 朴素贝叶斯判别实验

一、实验目的

1、复习朴素贝叶斯判别的原理和算法
2、使用朴素贝叶斯判别对鸢尾花数据集进行分类

二、实验原理

贝叶斯决策就是在不完全情况下,对部分未知的状态用主观概率估计,然后用贝叶斯公式对发生概率进行修正,最后再利用期望值和修正概率做出最优决策。

贝叶斯决策理论方法是统计模型决策中的一个基本方法,其基本思想是:
(1)已知类条件概率密度参数表达式和先验概率。
(2)利用贝叶斯公式转换成后验概率。
(3)根据后验概率大小进行决策分类。

三、实验代码

#导入所需要的包
from sklearn.naive_bayes import GaussianNB   # 朴素贝叶斯
import numpy as np
import pandas as pd
from pandas import Series,DataFrame
import matplotlib.pyplot as plt
from sklearn.datasets import load_iris         # 鸢尾花数据集
from matplotlib.colors import ListedColormap   # 色彩设置

# 导入鸢尾花数据集
dataset = load_iris()
# 显示数据形状
print(dataset.data.shape)

x = dataset.data[:, : 2]  # 选前两个特征
y = dataset.target

# 定义朴素贝叶斯模型
muNB = GaussianNB()
muNB.fit(x, y)  # 训练

#取出训练数据中第一列中的最大与最小值
xmin,xmax = x[:, 0].min(), x[:, 0].max()

#取出训练数据中第二列中的最大与最小值
ymin,ymax = x[:, 1].min(), x[:, 1].max()

#在最大与最小值的区间分成300个数据
x_n = np.linspace(xmin,xmax,300)
y_n = np.linspace(ymin,ymax,300)

#然后使这些数据组成一个平面
xx, yy = np.meshgrid(x_n, y_n)

#生成90000个坐标点
x_test = np.c_[xx.ravel(),yy.ravel()]

#预测训练数据
y_ = muNB.predict(x_test)

#导入三种不同的颜色
colormap = ListedColormap(['#FF0000', '#00FF00', '#0000FF'])

#生成三个不同颜色的模块
plt.scatter(x_test[:,0],x_test[:,1],c=y_)
plt.scatter(x[:, 0], x[:, 1], c=y,cmap=colormap)
plt.show()

四、运行结果

运行结果

五、思考题

说明GussianNB函数中各参数的意义?

GussianNB函数的原型为:

class sklearn.naive_bayes.GaussianNB(*, priors=None, var_smoothing=1e-09)

其中每个参数的意义如下:

priors:array-like of shape (n_classes,),可输入任何类数组结构,形状为(n_classes,)表示类的先验概率。如果指定,则不根据数据调整先验,如果不指定,则自行根据数据计算先验概率。默认为None。

var_smoothing:在估计方差时,为了追求估计的稳定性,将所有特征的方差中最大的方差以某个比例添加到估计的方差中。此参数控制这个比例。默认为1e-09。

六、参考

scikit-learn 1.0.1

实验四 - 支持向量机实验

一、实验目的

1、复习支持向量机分类与支持向量回归相关概念
2、使用支持向量机对线性可分数据集进行分类,使用核函数进行非线性分类
3、使用支持向量回归对有噪声的函数波形进行回归分析

二、实验原理

最大间隔分离超平面的存在唯一性:若训练数据集T线性可分,则可将训练数据集中的样本点完全正确分开的最大间隔分离超平面存在且唯一。

三、实验代码

'''
--------------------------------------------------------------------
--------------------------------------------------------------------
-------------------------支持向量机分类实验-------------------------
--------------------------------------------------------------------
--------------------------------------------------------------------
'''

# 导入所需要的包
import numpy as np
from matplotlib import colors
from sklearn import svm  # 支持向量机
from sklearn.datasets import load_iris  # 鸢尾花数据集
from sklearn import model_selection
import matplotlib.pyplot as plt
import matplotlib as mpl

# 导入鸢尾花数据集
dataset = load_iris()
# 显示数据形状
print(dataset.data.shape)

x = dataset.data[:, : 2]  # 选前两个特征
y = dataset.target

# 定义SVM模型,线性核函数
clf = svm.SVC(C=0.8, kernel='linear', decision_function_shape='ovr')
# 训练模型
clf.fit(x, y.ravel())


def draw(clf, x):
    iris_feature = 'sepal length', 'sepal width', 'petal length', 'petal width'
    # 开始画图
    x1_min, x1_max = x[:, 0].min(), x[:, 0].max()
    x2_min, x2_max = x[:, 1].min(), x[:, 1].max()
    # 生成网格采样点
    x1, x2 = np.mgrid[x1_min:x1_max:200j, x2_min:x2_max:200j]
    # 测试点
    grid_test = np.stack((x1.flat, x2.flat), axis=1)
    grid_hat = clf.predict(grid_test)
    # 使得grid_hat 和 x1 形状一致
    grid_hat = grid_hat.reshape(x1.shape)
    cm_light = mpl.colors.ListedColormap(['#A0FFA0', '#FFA0A0', '#A0A0FF'])
    cm_dark = mpl.colors.ListedColormap(['g', 'b', 'r'])

    plt.pcolormesh(x1, x2, grid_hat, cmap=cm_light)
    plt.scatter(x[:, 0], x[:, 1], c=np.squeeze(y), edgecolor='k', s=50, cmap=cm_dark)
    plt.xlabel(iris_feature[0], fontsize=20)
    plt.ylabel(iris_feature[1], fontsize=20)
    plt.xlim(x1_min, x1_max)
    plt.ylim(x2_min, x2_max)
    plt.title('Iris data classification via SVM', fontsize=15)
    plt.grid()
    plt.show()


draw(clf, x)

# 多项式核函数
clf = svm.SVC(C=0.8, kernel='poly', degree=3, decision_function_shape='ovr')
# 训练模型
clf.fit(x, y.ravel())

draw(clf, x)

'''
--------------------------------------------------------------------
--------------------------------------------------------------------
-------------------------支持向量机回归实验-------------------------
--------------------------------------------------------------------
--------------------------------------------------------------------
'''

# 导入所需要的包
import numpy as np
from matplotlib import colors
from sklearn import svm  # 支持向量机
from sklearn import model_selection
import matplotlib.pyplot as plt
import random


# flag:是否添加噪声,为true则添加噪声
def load_data(flag):
    x1_train = np.linspace(0, 50, 30)
    if (flag):
        data_train = np.array([[x1, 2 * x1 + (np.random.random(1) - 0.5)] for x1 in x1_train])
    else:
        data_train = np.array([[x1, 2 * x1] for x1 in x1_train])
    return data_train


# 未添加噪声
x0 = load_data(False)[:, 0].reshape(-1, 1)
y0 = load_data(False)[:, 1]
plt.scatter(x0, y0)

# 添加噪声
x1 = load_data(True)[:, 0].reshape(-1, 1)
y1 = load_data(True)[:, 1]
plt.scatter(x1, y1)


def function(model, x, y):
    model.fit(x, y)
    result = model.predict(x)
    plt.figure()
    plt.plot(np.arange(len(result)), y, 'go-', label='true value')
    plt.plot(np.arange(len(result)), result, 'ro-', label='predict value')
    plt.legend()
    plt.show()


model1 = svm.SVR(kernel='linear')
function(model1, x1, y1)


# 二次函数
def load_data2():
    x1_train = np.linspace(0, 50, 30)
    data_train = np.array([[x1, x1 * x1 + 3] for x1 in x1_train])
    return data_train


x2 = load_data2()[:, 0].reshape(-1, 1)
y2 = load_data2()[:, 1]
plt.scatter(x2, y2)

# 线性核函数
model2 = svm.SVR(kernel='linear')
function(model2, x2, y2)

# 多项式核函数
model3 = svm.SVR(kernel='poly')
function(model3, x2, y2)

四、运行结果

支持向量机分类

支持向量机回归

五、思考题

1、分析核函数对支持向量机分类性能的影响
  • 核函数的引入避免了“维数灾难”,大大减小了计算量;
  • 核函数方法可以有效处理高维输入;
  • 无需知道非线性变换函数的形式和参数;
  • 核函数的形式和参数的变化会隐式地改变从输入空间到特征空间的映射,进而对特征空间的性质产生影响,最终改变各种核函数方法的性能;
  • 核函数方法可以和不同的算法相结合,形成多种不同的基于核函数技术的方法。
2、论述支持向量回归与一般回归方法的区别
  • 支持向量回归与一般回归的相同点:
    (1)支持向量回归与一般回归都是监督学习算法;
    (2)支持向量回归与一般回归都是判别模型;
    (3)若不考虑核函数,则支持向量回归与一般回归都是线性分类算法;
  • 支持向量回归与一般回归的不同点:
    (1)损失函数不同;
    (2)SVM只考虑支持向量,一般回归考虑全局;
    (3)训练集较小时,支持向量方法更适合;

实验五 - 主成分分析实验

一、实验目的

1、复习主成分分析的原理和算法
2、使用sklearn库函数实现对鸢尾花数据集的主成分分析,观察主成分分析的作用
3、(选做)解读基于主成分分析和支持向量机的人脸识别程序

二、实验代码

from time import time
import logging
import matplotlib.pyplot as plt

from sklearn.model_selection import train_test_split
from sklearn.model_selection import GridSearchCV
from sklearn.datasets import fetch_lfw_people
from sklearn.metrics import classification_report
from sklearn.metrics import confusion_matrix
from sklearn.decomposition import PCA
from sklearn.svm import SVC

# Display progress logs on stdout
logging.basicConfig(level=logging.INFO, format="%(asctime)s %(message)s")

# #############################################################################
# Download the data, if not already on disk and load it as numpy arrays

lfw_people = fetch_lfw_people(min_faces_per_person=70, resize=0.4)

# introspect the images arrays to find the shapes (for plotting)
n_samples, h, w = lfw_people.images.shape

# for machine learning we use the 2 data directly (as relative pixel
# positions info is ignored by this model)
X = lfw_people.data
n_features = X.shape[1]

# the label to predict is the id of the person
y = lfw_people.target
target_names = lfw_people.target_names
n_classes = target_names.shape[0]

print("Total dataset size:")
print("n_samples: %d" % n_samples)
print("n_features: %d" % n_features)
print("n_classes: %d" % n_classes)

# #############################################################################
# Split into a training set and a test set using a stratified k fold

# split into a training and testing set
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.25, random_state=42
)

# #############################################################################
# Compute a PCA (eigenfaces) on the face dataset (treated as unlabeled
# dataset): unsupervised feature extraction / dimensionality reduction
n_components = 150

print(
    "Extracting the top %d eigenfaces from %d faces" % (n_components, X_train.shape[0])
)
t0 = time()
pca = PCA(n_components=n_components, svd_solver="randomized", whiten=True).fit(X_train)
print("done in %0.3fs" % (time() - t0))

eigenfaces = pca.components_.reshape((n_components, h, w))

print("Projecting the input data on the eigenfaces orthonormal basis")
t0 = time()
X_train_pca = pca.transform(X_train)
X_test_pca = pca.transform(X_test)
print("done in %0.3fs" % (time() - t0))

# #############################################################################
# Train a SVM classification model

print("Fitting the classifier to the training set")
t0 = time()
param_grid = {
    "C": [1e3, 5e3, 1e4, 5e4, 1e5],
    "gamma": [0.0001, 0.0005, 0.001, 0.005, 0.01, 0.1],
}
clf = GridSearchCV(SVC(kernel="rbf", class_weight="balanced"), param_grid)
clf = clf.fit(X_train_pca, y_train)
print("done in %0.3fs" % (time() - t0))
print("Best estimator found by grid search:")
print(clf.best_estimator_)

# #############################################################################
# Quantitative evaluation of the model quality on the test set

print("Predicting people's names on the test set")
t0 = time()
y_pred = clf.predict(X_test_pca)
print("done in %0.3fs" % (time() - t0))

print(classification_report(y_test, y_pred, target_names=target_names))
print(confusion_matrix(y_test, y_pred, labels=range(n_classes)))

# #############################################################################
# Qualitative evaluation of the predictions using matplotlib

def plot_gallery(images, titles, h, w, n_row=3, n_col=4):
    """Helper function to plot a gallery of portraits"""
    plt.figure(figsize=(1.8 * n_col, 2.4 * n_row))
    plt.subplots_adjust(bottom=0, left=0.01, right=0.99, top=0.90, hspace=0.35)
    for i in range(n_row * n_col):
        plt.subplot(n_row, n_col, i + 1)
        plt.imshow(images[i].reshape((h, w)), cmap=plt.cm.gray)
        plt.title(titles[i], size=12)
        plt.xticks(())
        plt.yticks(())

# plot the result of the prediction on a portion of the test set

def title(y_pred, y_test, target_names, i):
    pred_name = target_names[y_pred[i]].rsplit(" ", 1)[-1]
    true_name = target_names[y_test[i]].rsplit(" ", 1)[-1]
    return "predicted: %s\ntrue:      %s" % (pred_name, true_name)

prediction_titles = [
    title(y_pred, y_test, target_names, i) for i in range(y_pred.shape[0])
]

plot_gallery(X_test, prediction_titles, h, w)

# plot the gallery of the most significative eigenfaces

eigenface_titles = ["eigenface %d" % i for i in range(eigenfaces.shape[0])]
plot_gallery(eigenfaces, eigenface_titles, h, w)

plt.show()

三、运行结果

运行结果

四、思考题

绘制人脸识别程序的流程框图

流程框图

实验六 - 奇异值分解实验

一、实验目的

1、复习奇异值分解的原理
2、使用奇异值分解对简单矩阵进行分解,观察分解结果
3、使用奇异值分解进行图像压缩

二、实验代码

import numpy as np

# 生成3*3矩阵
data = np.matrix([[1,2,3],[4,5,6],[7,8,9]])
print('data.shape:{}\n\ndata:\n{}\n'.format(data.shape,data))

# 奇异值分解
u, sigma, v = np.linalg.svd(data)

print('u:\n{}\n\nsigma:\n{}\n\nv:\n{}\n'.format(u,sigma,v))

from PIL import Image
import matplotlib.pyplot as plt

# 导入图片
img =Image.open("./img2.jpg")
print("图像尺寸:{}".format(img.size))
plt.imshow(img)
plt.show()

# 将图片转换成numpy.ndarray
img = np.array(img)
print(img.shape)

# 对图片进行奇异值分解
u, sigma, v = np.linalg.svd(img[:,:,0])

def rebuild_img(u,sigma,v,p):  # p表示奇异值的百分比
     m=len(u)
     n=len(v)
     a=np.zeros((m,n))
 
     count=(int)(sum(sigma))
     curSum=0
     k=0
 
     while curSum<=count*p:
         uk=u[:,k].reshape(m,1)
         vk=v[k].reshape(1,n)
         a+=sigma[k]*np.dot(uk,vk)
         curSum+=sigma[k]
         k+=1
 
     a[a<0]=0
     a[a>255]=255
  
     return np.rint(a).astype("uint8")

ls = []
# 奇异值的百分比从0.1到0.9
for p in np.arange(0.1, 1, 0.1):
    # 重构分解后的图片
    newImg = rebuild_img(u,sigma,v,p)
    # 将array转换为图片,保存到ls中
    ls.append(Image.fromarray(newImg))

# 显示全部图片
plt.figure(figsize=(12,12))
for i in range(0,9): 
    plt.subplot(3, 3, i + 1)
    plt.imshow(ls[i])
plt.show()

三、运行结果

原始图片

奇异值分解结果

四、思考题

简述奇异值分解进行图像压缩的原理

奇异值分解可以用于图像压缩,通过降维处理,在尽可能不损失画质的情况下,有效减少图片储存所需的空间。
通常在像素矩阵中,奇异值之间大小差距非常悬殊,因此我们只需要对前面奇异值较大,包含信息较多的“子信息空间”进行合成,舍去后面影响微小的“子信息空间”,就可以在节省存储空间的同时,保留尽可能多的图像信息,从而实现图像压缩。

最后修改:2021 年 12 月 19 日 10 : 22 AM