0 实验环境

python 3.7.0

  • matplotlib
  • scikit-learn

1 预备知识

估计器(Estimator):用于分类、聚类和回归分析。
转换器(Transformer):用于数据预处理和数据转换。
流水线(Pipeline):组合数据挖掘流程,便于再次使用。

欧式距离:连接两点的线段的长度(特征向量长度平方和的平方根)

某些特征取值巨大(离群点)时效果会很差。
	稀疏矩阵效果也很差。

曼哈顿距离:两个特征在标准坐标系中绝对轴距之和
余弦距离:特征向量夹角的余弦值

更适合解决异常值和数据稀疏问题

采用哪种距离度量方法对最终结果有很大影响。

此处我们选用欧氏距离做为实验。


2 加载数据集

我们使用Ionosphere数据集。
URL: http://archive.ics.uci.edu/ml/datasets/Ionosphere 下载ionosphere.dataionosphere.names(我是把文件放在主目录下的data文件夹然后新建了一个ionosphere文件夹)
让图片直接出在jupyter里我们需要做一个配置:

%matplotlib inline

获取主目录

import os
home_folder = os.path.expanduser("~")
print(home_folder)
data_folder = os.path.join(home_folder,"data","ionosphere")
data_filename = os.path.join(data_folder,"ionosphere.data")
print(data_filename)

笔者的测试环境是win10
故输出:
C:\Users\skysys\data\ionosphere\ionosphere.data

然后开始加载数据集,该数据集每行35个值,前34个为17座天线采集的数据(每座天线采集两个数据)最后一个值为g或者是b,表示数据的好坏(是否提供了有价值的信息)
我们的任务是建立一个分类器,判断数据的好坏。

import numpy as np
import csv
x = np.zeros((351,34),dtype='float')
y = np.zeros((351,),dtype='bool')
with open(data_filename,'r') as input_file:
    reader = csv.reader(input_file)
    for i,row in enumerate(reader):
        data = [float(datum) for datum in row[:-1]]
        x[i] = data
        y[i] = row[-1] == 'g'

3 数据处理

scikit-learn内部实现了大量的分类算法,把相关功能封装成一个估计器,用于分类任务。主要包含以下两个函数:

  • fit():训练算法,设置内部参数。 参数为训练集和类别
  • predict():参数为测试集。返回预测结果。

本文选择近邻算法

划分数据集:

from sklearn.model_selection import train_test_split
x_train,x_test,y_train,y_test = train_test_split(x,y,random_state=14)
print("There are {} samples in the training dataset".format(x_train.shape[0]))
print("There are {} samples in the testing dataset".format(x_test.shape[0]))
print("Each sample has {} features".format(x_train.shape[1]))

There are 263 samples in the training dataset
There are 88 samples in the testing dataset
Each sample has 34 features

近邻算法思想:为了对新个体分类,查找训练集,找到与新个体最相似的那些个体,这些个体大多属于的类别就是新个体的类别。
该算法在特征值取离散值时效果很差。
为了实现这个算法,重点需要衡量两个个体的相似度,在文章开头介绍过的几种距离都是常用的方式。

然后我们借助scikit-learn来实现:
导入k近邻估计器:

from sklearn.neighbors import KNeighborsClassifier
estimator = KNeighborsClassifier()

开始训练:

estimator.fit(x_train,y_train)

输出:KNeighborsClassifier(algorithm=‘auto’, leaf_size=30, metric=‘minkowski’,
metric_params=None, n_jobs=None, n_neighbors=5, p=2,
weights=‘uniform’)

4 算法评估

评估算法:

y_predicted = estimator.predict(x_test)
accuracy = np.mean(y_test == y_predicted)*100
print("The accuracy is {0:.1f}%".format(accuracy))

The accuracy is 86.4%


5 交叉检验

avg_scores = []
all_scores = []
parameter_values = list(range(1,21))
for n_neighbors in parameter_values:
    estimator = KNeighborsClassifier(n_neighbors=n_neighbors)
    scores = cross_val_score(estimator,x,y,scoring='accuracy')
    avg_scores.append(np.mean(scores))
    all_scores.append(scores)

可能会报futureWarning,有强迫症的话参考笔者之前写过的一篇博客消futureWarning:

作图

from matplotlib import pyplot as plt
plt.figure(figsize=(32,20))
plt.plot(parameter_values,avg_scores,'-o',linewidth=5,markersize=24)

python对soh估算_python对soh估算

for parameter,scores in zip(parameter_values,all_scores):
    n_scores = len(scores)
    plt.plot([parameter] * n_scores,scores,'-o')

python对soh估算_分类_02

plt.plot(parameter_values,all_scores,'bx')

python对soh估算_k近邻_03

from collections import defaultdict
all_scores = defaultdict(list)
parameter_values = list(range(1, 21))  # Including 20
for n_neighbors in parameter_values:
    for i in range(100):
        estimator = KNeighborsClassifier(n_neighbors=n_neighbors)
        scores = cross_val_score(estimator, X, y, scoring='accuracy', cv=10)
        all_scores[n_neighbors].append(scores)
for parameter in parameter_values:
    scores = all_scores[parameter]
    n_scores = len(scores)
    plt.plot([parameter] * n_scores, scores, '-o')

python对soh估算_分类_04