Python数据挖掘算法入门与实践

共 21709字,需浏览 44分钟

 ·

2024-04-10 16:09

一、数据挖掘简介

数据挖掘是一个通过对大量数据进行清理和处理,以发现其中隐藏的信息和模式的过程。简单来说,它是从大量数据中提取或“挖掘”知识的过程,也称为知识发现。


随着互联网和移动工具的发展,我们每天产生的数据量非常庞大,这些数据通常被收集并存储在大型数据库中。数据挖掘技术提供了一种有效的方法,可以从这些海量数据中提取有价值的信息,从而为决策提供重要依据 。这个过程在许多领域都有广泛的应用,如新闻 分类、推荐系统等。


数据挖掘一般的流程如下:


d44cd7ac82e6885d79e777ebf9c50a7e.webp

  1. 首先,进行数据挖掘的第一步是数据选择。在明确了业务需求后,我们需要从各种来源中选择与需求相关的数据。这些数据可能来自业务原始数据、公开的数据集,或者通过爬虫从网站上抓取的结构化数据。选择合适的数据是进行数据挖掘的基础。

  2. 接下来是数据预处理阶段。在这个阶段,我们需要对选定的数据进行清洗和处理,以消除其中的噪音和不完整信息。

  3. 完成数据预处理后,我们进入特征工程或数据转换阶段。这个阶段的目标是根据所选择的算法,从预处理好的数据中提取出有意义的特征,并将其转换为适合特定数据挖掘算法的分析模型。

  4. 然后是数据挖掘阶段。在这个阶段,我们将使用选定的数据挖掘算法对处理过的数据进行深入分析,以发现其中的模式和关联。

  5. 最后是解释与评价阶段。在这个阶段,我们将对数据挖掘的结果进行解释和评价,以便将其应用于实际的工作领域。



二、数据挖掘算法简介


044b00c13f46bbea501cd9bfa145c865.webp

2.1 关联分析
关联规则分析的目标是发现数据集中不同属性之间的关联。为了达到这个目标,关联规则算法设置了最小支持度阈值和最小置信度阈值。这些算法致力于在尽可能高效的方式下完成这个任务。

常见的关联规则算法包括Apriori算法、AprioriTid算法和FP-growth算法。

315bc378aa684976ae7b7a7f4d77ff66.webp

2.2 分类算法
分类算法的目标是将数据集中的对象分配到预定义的类别中。以下是几种经典的分类算法:

6fa0b840fddd07fe46978c446c7916b0.webp

  • 决策树算法:使用树形结构表示分类或决策集合,从而产生规则或发现规律。主要的算法包括ID3、C4.5、SLIQ、SPRING和RainForest。

  • 朴素贝叶斯分类算法:基于贝叶斯定理,通过计算每个类别的概率来选择概率最大的类别进行分类。

  • KNN分类算法:基于最近邻原理,将距离相近的归为同一类。

  • CBA(基于关联规则的分类算法):利用关联规则进行分类。

  • MIND(在数据库中挖掘)算法:使用用户定义的函数(UDF)在数据库中实现分类的算法。

  • 神经网络分类算法:利用训练集对多层的神经网络进行训练,然后用训练好的模型对样本进行分类。

  • 粗集理论:一种不需要预先给出特征或属性数量描述的分类方法,直接从问题出发,通过不可分辨关系和不可分辨类确定近似域,找出问题的内在规律。

  • 遗传算法:模拟生物进化过程的优化求解技术,利用选择、交叉和变异三个基本方法进行优化。

2.3 回归分析

回归分析主要研究因变量(目标)和自变量(预测器)之间的关系。在大数据分析中,回归分析是一种预测性的建模技术,它通过研究因变量和影响它的自变量之间的回归模型,来预测因变量的发展趋势。当有多个自变量时,可以研究每个自变量对因变量的影响强度。

466ec4bc4455f5a3ac7bbe896b61e50f.webp

回归分析的分类如下:

  • 按自变量的多少分为:一元回归分析和多元回归分析。

  • 按因变量的多少分为:简单回归分析和多重回归分析。

  • 按自变量和因变量之间的相关关系不同分为:线性回归分析和非线性回归分析。

2.4 聚类算法
聚类分析处理的对象集合中,对象的类是未知的。它的目标是将对象集合分组为多个由类似对象组成的簇。聚类分析的方法可以分为以下三类:

8991c7532a71d9ba6c2fad7ba9c03805.webp

  • 分区方法:给定一个包含N个对象或元组的数据库,分区方法构建数据的K个划分,每个划分表示一个聚簇,且K < N。经典算法是K-MEAN(K平均值)算法。

  • 层次方法:对给定的数据对象集合进行层次的分解。经典算法是BIRCH(平衡迭代减少和聚类使用层次结构)算法。

  • 基于网格的方法:采用多分辨率的网格数据结构,将空间量化为有限数目的单元,形成网格结构,所有的聚类分析都在网格上进行。常用的算法有STING(统计信息网格)、CLIQUE(基于网格的聚类)和SKWAVECLUSTER(声波聚类)等。


三、相关预备知识


3.1 距离(相似度)度量

距离度量可用于在数据挖掘中明确样本数据相似度,通常可以计算样本间的距离,如下为常用距离度量的介绍。

样本数据以如下三个人的身高体重示例:6090d5de833da3d3ebec986d35d3b727.webp展示到坐标图中是这样的:

938173dcc0da58b51c3cb59b17d6d071.webp

曼哈顿距离: 也称曼哈顿街区距离,就如从街区的一个十字路口点到另一个十字路口点的距离, 二维空间(多维空间按同理扩展)用公式表示为


a8fb0e75ea985475d01588203df60058.webp



861894aeb3a5a1debb0d67665bdf862b.webp



欧氏距离:表示为点到点的距离。二维空间(多维空间按同理扩展)的公式表示为


d6f2def758c9b14834a092cce9b1b297.webp



1fcda95b70290c64d19d0f93de0d6dc7.webp



闵可夫斯基距离:其实就是距离方法的通用概括,当 p=1 既是曼哈顿距离,当 p=2 既是欧氏距离。当p越大,单一维度的差值对整体的影响就越大。


e8119e59d3312dda4415ccfb833934f1.webp


余弦相关系数

样本数据视为向量,通过两向量间的夹角余弦值确认相关性,数值范围[-1,1]。-1表示负相关,0表示无关,1表示正相关。

09480f5cfbad4ed809139b8c3449d0f2.webp余弦相关系数的优缺点:

优点:余弦相似度与向量的幅值无关,只与向量的方向相关,在文档相似度(TF-IDF)和图片相似性(histogram)计算上都有它的身影;而且在样本数值稀疏的时候仍可以使用。

缺点:余弦相似度受到向量的平移影响,上式如果将 x 平移到 x+1, 余弦值就会改变。(可以理解为受样本的起始标准的影响,接下来介绍的皮尔逊相关系数可以消除这个影响)

皮尔逊相关系数

计算出了样本向量间的相关性,数值范围[-1,1]。 f40215a1d52f19a46f992fd9829f5b47.webp

考虑计算的遍历的次数,有一个替代公式可以近似计算皮尔逊相关系数:

d2dd426637b9872c905e332803593c3d.webp

皮尔逊相关系数优点:可消除每个分量标准不同(分数膨胀)的影响,具有平移不变性和尺度不变性


3.2 数据标准化

数据中如果各分量的单位尺度差异很大,可以使用数据标准化消除不同分量间单位尺度的影响,,加速模型收敛的效率,常用的方法有三种:

min-max 标准化:将数值范围缩放到(0,1),但没有改变数据分布。max为样本最大值,min为样本最小值。

a378ceb4b3a71a0596ba4489ce2477f8.webp

z-score 标准化:将数值范围缩放到0附近, 经过处理的数据符合标准正态分布。u是平均值,σ是标准差。


59d9e0ca8e3055470c2819d866b7ecb9.webp

修正的标准z-score:修正后可以减少样本数据异常值的影响。将z-score标准化公式中的均值改为中位数,将标准差改为绝对偏差。

33c03eddd2d78ed0a2103a326f6f1fa0.webp

其中asd绝对偏差:u为中位数,card(x)为样本个数

dda52ea2b32075cb385fc23e01d2fc38.webp



3.3 算法的效果评估方法

  • 十折交叉验证:将数据集随机分成十份,每次使用九份进行训练,剩余一份进行测试,这个过程重复十次,确保每份数据都至少被使用过一次作为测试集。关键在于保证数据集被均匀地分成十份。

  • N折交叉验证:又称为留一法,它利用几乎所有的数据来进行训练,然后留出一份数据进行测试。这个过程会迭代进行,确保每一份数据都被用作过测试集。

  • 训练-测试划分验证:随机将数据集划分为训练集和验证集,用于评估模型的性能。


四、数据挖掘算法原理及实践


  1. 4.1 Apriori关联分析算法

模型原理:Apriori算法是一种用于频繁项集挖掘和关联规则学习的算法。其主要思想是通过候选生成和剪枝策略发现频繁项集。它利用了数据集中的项集(items)的先验知识,通过减少不必要的搜索来提高效率。a195632f1027d4f5b15f01ee39baf155.webp

使用场景:常用于市场篮子分析,如超市购物篮分析,以发现商品之间的关联关系。

Python示例代码:

        
          

              
                from mlxtend.frequent_patterns import apriori  
              
              
                from mlxtend.frequent_patterns import association_rules  
              
              
                
                  
# 假设df是包含交易数据的DataFrame,'item'是商品列 frequent_itemsets = apriori(df, min_support=0.05, use_colnames=True) rules = association_rules(frequent_itemsets, metric="confidence",min_threshold=0.7)
 

4.2 协同过滤推荐算法

基于用户的协同过滤是通过计算用户之间的距离找出最相似的用户(需要将所有的评价数据在读取在内存中处理进行推荐),并将相似用户评价过的物品推荐给目标用户。

7dda768066a452f3dfe7b447e684bfaf.webp

而基于物品的协同过滤则是找出最相似的物品(通过构建一个物品的相似度模型来做推荐),再结合用户的评价来给出推荐结果。算法常用有 修正余弦相似度算法:以物品的评分作为物品的属性值,通过对比物品i,j的共有的用户相对评分的计算相关性s(i,j)。

d584db4c83af56f553ebb50a6666f1b7.webp

Python示例代码:

          
            import numpy as np  
          
          
            
              
# 用户-物品评分矩阵 ratings = np.array([[5, 3, 0, 1], [4, 0, 0, 0], [0, 5, 3, 0], [0, 4, 5, 5]])
# 计算用户之间的相似度 def similarity(ratings): n = ratings.shape[0] sim = np.zeros((n, n)) for i in range(n): for j in range(n): if i != j: sim[i][j] = np.corrcoef(ratings[i], ratings[j])[0, 1] return sim
# 基于用户的协同过滤推荐算法 def user_based_collaborative_filtering(ratings, threshold=0.6): n = ratings.shape[0] sim = similarity(ratings) rec_list = {} for i in range(n): for j in range(n): if i != j and sim[i][j] > threshold: for k in range(len(ratings[j])): if ratings[j][k] == 0 and ratings[i][k] != 0: rec_list[k] = ratings[i][k] return rec_list
# 获取推荐结果 rec_list = user_based_collaborative_filtering(ratings) print(rec_list)

4.3 分类算法

(1)基于物品特征值的KNN分类算法


代码实现:iris鸢尾花KNN分类算法

          
            ...
          
          
            
              
# KNN核心逻辑手写 def knn(self, oj_list): weight_dict = {"Iris-setosa":0.0, "Iris-versicolor":0.0, "Iris-virginica":0.0} for atuple in oj_list: weight_dict[atuple[1]] += (1.0 / atuple[0]) rel_class = [(key, value) for key, value in weight_dict.items()] #print(sorted(rel_class, key=lambda x:x[1], reverse=True)) rel_class = sorted(rel_class, key=lambda x:x[1], reverse=True)[0][0] return rel_class
... # 调用sklearn直接实现 from sklearn.datasets import load_iris from sklearn.model_selection import train_test_split from sklearn.neighbors import KNeighborsClassifier from sklearn.metrics import classification_report, confusion_matrix
# 加载鸢尾花数据集 iris = load_iris() X = iris.data y = iris.target
# 划分数据集为训练集和测试集 X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 创建KNN分类器,并设置邻居数量为3 knn = KNeighborsClassifier(n_neighbors=3)
# 使用训练数据训练KNN分类器 knn.fit(X_train, y_train)
# 使用测试数据进行预测 y_pred = knn.predict(X_test)
# 输出分类器的评估结果 print("Classification Report:\n", classification_report(y_test, y_pred)) print("Confusion Matrix:\n", confusion_matrix(y_test, y_pred))

前面我们讨论的协同推荐算法,需要在用户生成的各种数据上进行深入分析,因此也被称为社会化过滤算法。然而,这种算法存在一些明显的问题,如数据的稀疏性、算法的可扩展性,以及过度依赖用户数据。为了解决这些问题,我们可以采用基于物品特征值分类的算法。

这个算法主要分为两个步骤: 第一步是特征值的选取。这一步是至关重要的,因为它决定了算法的准确性和效率。我们需要挑选出具有代表性且能提供区分度的特征值。以Iris花为例,我们可以选取花萼长度、花萼宽度、花瓣长度和花瓣宽度作为特征值。 a969bcaccc96c519cadb67e424ea7c6b.webp第二步是计算距离。在这一步中,我们将测试集与训练集的特征值进行比较,计算它们之间的曼哈顿距离。通过这种方式,我们可以找到与测试集最相似的k个训练样本。然后,我们使用加权后的结果来预测分类。
然而,KNN分类算法也存在一些缺点。首先,它无法对分类结果的置信度进行量化,这意味着我们无法确定分类的准确性。其次,它是一种被动学习的算法,这意味着每次进行测试时都需要遍历所有的训练集,这可能导致算法的效率较低。


(2)贝叶斯分类算法


代码实现:

          
            ...
          
          
            
              # bayes 核心逻辑手写
            
          
          
            
              def bayes(self):
            
          
          
            
              #训练组的条件概率
            
          
          
            for word in self.vocabulary:
          
          
            for category,value in self.prob.items():
          
          
            if word not in self.prob[category]:
          
          
            count = 0
          
          
            else :
          
          
            count = self.prob[category][word]
          
          
            
              #优化条件概率公式
            
          
          
            self.prob[category][word] = (count + 1) / (self.total[category] + len(self.vocabulary)) 
          
          
            
              
... # 调用sklearn实现 from sklearn.feature_extraction.text import CountVectorizer from sklearn.naive_bayes import MultinomialNB from sklearn.model_selection import train_test_split from sklearn.metrics import accuracy_score import pandas as pd
# 假设你有一个文本数据集,存储在CSV文件中,有两列:'text'和'label' data = pd.read_csv('text_data.csv')
# 提取特征和标签 X = data['text'].values y = data['label'].values
# 切分数据集为训练集和测试集 X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 使用CountVectorizer将文本转换为向量 vectorizer = CountVectorizer() X_train_transformed = vectorizer.fit_transform(X_train) X_test_transformed = vectorizer.transform(X_test)
# 使用朴素贝叶斯分类器进行训练 classifier = MultinomialNB() classifier.fit(X_train_transformed, y_train)
# 对测试集进行预测 y_pred = classifier.predict(X_test_transformed)
# 计算准确率 accuracy = accuracy_score(y_test, y_pred) print(f"Accuracy: {accuracy}")

贝叶斯分类算法是基于概率的分类算法。相比于KNN分类算法,它是主动学习的算法,它会根据训练集建立一个模型,并用这个模型对新样本进行分类,速度也会快很多。


贝叶斯分类算法的理论基础是基于条件概率的公式(应用于现实中P(X|Y&Z)不直观得出,而P(Y|X)*P(Z|X)比较直观得出),并假设已存在的子事件(y,z...实际应用中会有多个)间是相互独立的(因此也称为朴素贝叶斯),当y,z事件假设为独立便有:



ee1b5e7c2ebe38178975094a98003d41.webp

如下举例推测买牛奶和有机食品,再会买绿茶的概率:


442326c013f6518bf42c4d485b28a56c.webp



第一步:计算先验概率及条件概率

先验概率:为单独事件发生的概率,如P(买绿茶),P(有机食品)

条件概率(后验概率):y事件已经发生,观察y数据集后得出x发生的概率。如P(买有机食品|买绿茶),通过以下公式计算(nc表示y数据集下x的发生频数,n为y数据集的总数):



91605a2a19a2eb748515ceae96e73491.webp

上式存在一个缺陷,当一个条件概率 P(y|x)为0时,整体的预测结果P(x) * P(y|x) * P(z|x)只能为0,这样便不能更全面地预测。



修正后的条件概率:(公式摘自Tom Mitchell《机器学习》。m是一个常数,表示等效样本大小。决定常数m的方法有很多,我们这里可以使用预测结果的类别来作为m,比如投票有赞成和否决两种类别,所以m就为2。p则是相应的先验概率,比如说赞成概率是0.5,那p(赞成)就是0.5。):



d6ab8692cdb7f5d21734ccce0e2c9279.webp



第二歩:根据贝叶斯公式做出预测



ee1b5e7c2ebe38178975094a98003d41.webp



由公式计算比较y&z事件发生下,不同x事件发生的概率差异,如得出P(x=喜欢),P(x=不喜欢) 的概率大小,预测为概率比较大的事件。因为P(y)*p(z)在上式都一样,因此公式可以简化为计算概率最大项而预测分类:


6024bae9d029d21bcaaa487d8348de50.webp



贝叶斯算法的优点:能够给出分类结果的置信度;它是一种主动学习算法,速度更快。

贝叶斯算法的缺点:需要特定格式;数值型数据需要转换为类别计算概率或用高斯分布计算概率;


(3)神经网络(DNN)分类算法


代码实现 :

          
            
              import tensorflow as tf  
            
          
          
            
              from tensorflow.keras import layers, models  
            
          
          
            
              import numpy as np  
            
          
          
            
              import matplotlib.pyplot as plt  
            
          
          
            
              import cv2  
            
          
          
            
              
# 加载数据集,这里我们使用的是MNIST数据集,你可以替换成自己的数据集 (train_images, train_labels), (test_images, test_labels) = tf.keras.datasets.mnist.load_data()
# 对数据进行归一化处理 train_images = train_images / 255.0 test_images = test_images / 255.0
# 构建DNN模型 model = models.Sequential() model.add(layers.Dense(512, activation='sigmoid', input_shape=(28, 28))) # 输入层,28x28是MNIST图片的大小 model.add(layers.Dense(512, activation='sigmoid')) # 隐藏层 model.add(layers.Dense(10, activation='softmax')) # 输出层,10个类别,使用softmax激活函数进行多分类
# 编译模型,设置损失函数、优化器和评估指标 model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])
# 训练模型 model.fit(train_images, train_labels, epochs=5)
# 在测试集上评估模型性能 test_loss, test_acc = model.evaluate(test_images, test_labels) print('\nTest accuracy:', test_acc)
# 使用模型进行预测并可视化结果 predictions = model.predict(test_images) predicted_class = np.argmax(predictions, axis=1) # 获取预测类别 true_class = np.argmax(test_labels, axis=1) # 获取真实类别 plt.figure(figsize=(10, 5)) for i in range(len(test_images)): plt.subplot(1, 2, i+1) plt.imshow(test_images[i].reshape(28, 28), cmap='gray') plt.title('Predicted: ' + str(predicted_class[i]) + ', True: ' + str(true_class[i])) plt.show()

DNN分类算法实现了输入图片特征向量X,输出Y(范围0~1)预测X的分类。

第一步,得到关于X线性回归函数

可以通过线性回归得到WX + b,其中W是权重,b是偏差值。但不能用本式表述预测的值,因为输出Y的值需要在(0~1)区间;

第二歩,通过激活函数转换

激活函数的特点是可以将线性函数转换为非线性函数,并且有输出值有限,可微分,单调性的特点。本例使用sigmoid,使输出为预测值Y=sigmoid(WX+b);

多个神经网络层,也就是重复第一、二步,类似sigmoid(sigmoid(WX+b))..的复合函数。

第三歩,构建Cost函数

训练W,b更好的预测真实的类别需要构建Cost代价函数,y^为sigmoid(WX+b)的预测分类值,y为实际分类值(0或者1):

52812566d17381942420bb238c406983.webp

其中L(y^,y)称为损失函数 e5d35e6dcf9b1049cc13397a5b9976e3.webp训练的目的就是为了让L(y^,y)足够小,也就是当y实际分类值为1时,y^要尽量偏向1。y实际分类值为0时,y^尽量小接近0。

第四步,梯度下降得到Cost函数的极小值

d3948dc5d54530cad6adb4adab91f7dd.webp通过对W,b两个参数求偏导,不断迭代往下坡的的位置移动(对w,b值往极小值方向做优化,其中α为学习率控制下降的幅度),全局最优解也就是代价函数(成本函数)J (w,b)这个凸函数的极小值点。 36726e03a38a789e656b84e33c43115f.webp第五步、通过训练好的W,b预测分类。 508c65dec9f9a113dddd037602be48de.webp


4.4 聚类算法

(1)层次聚类

层次聚类将每条数据都 当作是一个分类,每次迭代的时候合并距离最近的两个分类,直到剩下一个分类为止。

代码实现:

          
            from sklearn.cluster import AgglomerativeClustering  
          
          
            from sklearn.datasets import make_blobs  
          
          
            import matplotlib.pyplot as plt  
          
          
            
              
# 生成样本数据 X, y = make_blobs(n_samples=300, centers=4, cluster_std=0.60, random_state=0)
# 实例化层次聚类模型,n_clusters为聚类数 cluster = AgglomerativeClustering(n_clusters=4)
# 拟合数据 cluster.fit(X)
# 获取聚类标签 labels = cluster.labels_
# 绘制结果 plt.scatter(X[:, 0], X[:, 1], c=labels, cmap='viridis') plt.show()


(2)K-means++聚类


8aab069a49a1d55b22051d3b251504a6.webp

注:Kmean算法与Kmean++区别在于初始的中心点是直接随机选取k各点。

代码实现:

          
            from sklearn.cluster import KMeans  
          
          
            from sklearn import datasets  
          
          
            import matplotlib.pyplot as plt  
          
          
            
              
# 加载Iris数据集 iris = datasets.load_iris() X = iris.data y = iris.target
# 创建KMeans实例并拟合数据 kmeans = KMeans(n_clusters=3) kmeans.fit(X)
# 获取聚类标签和聚类中心点 labels = kmeans.labels_ centroids = kmeans.cluster_centers_
# 绘制聚类结果 plt.scatter(X[:, 0], X[:, 1], c=labels, cmap='viridis') plt.scatter(centroids[:, 0], centroids[:, 1], c='red', s=300) # 绘制聚类中心点 plt.show()

k-means++算法可概括为:

(1)基于各点到中心点得距离分量,依次随机选取到k个元素作为中心点:先随机选择一个点。重复以下步骤,直到选完k个点。

计算每个数据点dp(n)到各个中心点的距离(D),选取最小的值D(dp); f43f4333c84ac66ebe85289bdff6a620.webp根据D(dp)距离所占的份量来随机选取下一个点作为中心点。 e77e3622194c4120c0901e27ebdf0348.webp

(2)根据各点到中心点的距离分类;

(3)计算各个分类新的中心点。重复(2、3),直至满足条件。

浏览 21
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报