1. 程式人生 > >資料探勘學習(四)——常見案例總結

資料探勘學習(四)——常見案例總結

1、K-meaning演算法實戰

主要是通過均值來聚類的一個方法。

步驟為:

1)隨機選擇k個點作為聚類中心;

2)計算各個點到這k個點的距離,將距離相近的點聚集在一起,行程k個類;

3)將對應的點聚到與他最近的聚類中心;

4)分成k個聚類之後,重新計算聚類中心;

5)比較當前聚類中心與前一次聚類中心,如果是同一個點,則聚類收斂,得到聚類結果;如果為不同的點,則重複第二到五步。

#!/usr/bin/env python

# _*_ UTF-8 _*_
import numpy as npy
import pandas as pda
import matplotlib.pylab as pyl
# 通過程式實現錄取學生的聚類;

fname = "F:/python_workspace/file/collection_method/luqu.csv"
dataf = pda.read_csv(fname)
x = dataf.iloc[:
, 1:4].as_matrix()

from sklearn.cluster import Birch
from sklearn.cluster import KMeans
# 呼叫kmeans方法,指定聚4類。
kms = KMeans(n_clusters=4)
y = kms.fit_predict(x)
# 一個y代表一個點,數字表示屬於第幾類。
print(y)
print(x)
# x代表學生
s = npy.arange(
0, len(y))
pyl.plot(s
, y, "o")
pyl.show()
# 通過聚類實現商品的聚類:
# 淘寶商品的聚類:
import matplotlib.pylab as pyl
import pymysql
conn = pymysql.connect(
host="localhost",
                      
user="root",
                      
password="123456",
                       
db="livan",
                      
port=3306,
                      
charset='utf8')
sql=
"select price, comments from goods"
dataf2 = pda.read_sql(sql, conn)
x = dataf2.iloc[:
,:].as_matrix()
from sklearn.cluster import Birch
from sklearn.cluster import KMeans
# 呼叫kmeans方法,指定聚3類。
kms = KMeans(n_clusters=3)
y = kms.fit_predict(x)
print(y)
for i in range(0, len(y)):
   
if(y[i]==0):
        pyl.plot(dataf2.iloc[i:i+
1, 0:1].as_matrix(),
                
dataf2.iloc[i:i+1, 1:2].as_matrix(),
                 
"*r")
   
elif(y[i]==1):
        pyl.plot(dataf2.iloc[i:i+
1, 0:1].as_matrix(),
                
dataf2.iloc[i:i+1, 1:2].as_matrix(),
                
"sy")
   
elif(y[i]==2):
        pyl.plot(dataf2.iloc[i:i+
1, 0:1].as_matrix(),
                 
dataf2.iloc[i:i+1, 1:2].as_matrix(),
                
"pk")
pyl.show()
 

2、決策樹:

#!/usr/bin/env python
# _*_ UTF-8 _*_
import pandas as pda
# 資訊熵:信源的不確定度。

fname = "F:/python_workspace/file/lessons.csv"
dataf = pda.read_csv(fname)

# 提取某行列,然後轉換成矩陣[行,列]
x = dataf.iloc[:, 1:5].as_matrix()
y = dataf.iloc[:, 5].as_matrix()

# x為二維陣列,可以對其進行遍歷,遇到是、多等欄位變為1
# 遇到否、少等欄位變為0for i in range(0, len(x)):
    for j in range(0, len(x[i])):
        thisdata = x[i][j]
        if(thisdata =="" or thisdata=="" or thisdata==""):
            x[i][j] = int(1)
        else:
            x[i][j] = -1

for i in range(0, len(y)):
    thisdata = y[i]
    if(thisdata==""):
        y[i] = 1
    else:
        y[i] = -1

# 容易錯的地方:
# 正確的做法為:轉化好格式,將xy轉化為資料框,然後再轉化為陣列並制定格式。
xf = pda.DataFrame(x)
yf = pda.DataFrame(y)
x2 = xf.as_matrix().astype(int)
y2 = yf.as_matrix().astype(int)

# 建立決策樹:
from sklearn.tree import DecisionTreeClassifier as DTC
# 資訊熵的模式entropy
dtc = DTC(criterion="entropy")
dtc.fit(x2, y2)
# 直接預測銷量高低:
import numpy as npy
x3 = npy.array([[1, -1, -1, 1], [1, 1, 1, 1], [-1, 1, -1, 1]])
rst = dtc.predict(x3)
print(rst)

# 視覺化決策樹:
from sklearn.tree import export_graphviz
from sklearn.externals.six import StringIO
with open("F:/python_workspace/file/decision_tree/dtc.dot", "w") as file:
   
# 引數為:模式、特徵值(實戰、課時數、是否促銷、是否提供配套資料)
   
export_graphviz(dtc, feature_names=["combat", "num", "promotion", "datum"], out_file=file)
# 此時已經生成決策樹,但是dot的檔案打不開,此時需要使用graph的軟體開啟。

Dot的使用方法:

可以得到決策樹:

決策樹往左看——負能量;往右看——正能量;

Entropy是資訊熵,value是銷量高地的統計情況【14,15】:即14是銷量低的,15是銷量高的。決策樹會通過一層層的使用特徵值,來劃分資料。

3、邏輯迴歸:

求解邏輯迴歸引數的傳統方法是梯度下降,構造為凸函式的代價函式後,每次沿著偏導方向(下降速度最快方向)邁進一小部分,直至N次迭代後到達最低點。

#!/usr/bin/env python
# _*_ UTF-8 _*_

import pandas as pda

fname = "F:/python_workspace/file/logic/luqu.csv"
dataf = pda.read_csv(fname)

# [,]
x = dataf.iloc[:, 1:4].as_matrix()
y = dataf.iloc[:, 0:1].as_matrix()

from sklearn.linear_model import LogisticRegression as LR
from sklearn.linear_model import RandomizedLogisticRegression as RLR

# 建立一個邏輯迴歸模型
r1 = RLR()
# 訓練模型
r1.fit(x, y)
# 特徵值篩選,獲取有效特徵。
r1.get_support()
# print(dataf.columns[r1.get_support()])
# 將可用的特徵值引數轉換成陣列,用來預測y值。
t = dataf[dataf.columns[r1.get_support()]].as_matrix()

r2 = LR()
# 建立xy之間的關係並進行訓練。
r2.fit(t, y)
print("訓練結束")
print("模型正確率為:"+str(r2.score(x, y)))

4、貝葉斯分類器:

思路為:

1、給定一個訓練集、一個對應的標籤集,訓練集中的每一個數據點x(對應有多個維度(a1,a2,a3,a4))對應有一個標籤A,即該訓練集已經做好分類。

2、對給定的標籤集進行計算,各個標籤A在標籤集中佔的比例即為訓練集中某一類A出現的出現概率。

3、在訓練集中,某一類別中的資料有多個維度(a1,a2,a3,a4),各個維度值在這一類別A中的比例可以計算得出。

4、然後再使用貝葉斯公式計算新出現的資料的概率。

#!/usr/bin/env python
# _*_ UTF-8 _*_

import numpy as npy

# 貝葉斯分類:

class Bayes:
   
def __init__(self):
       
# -1表示測試方法沒有做,表示沒有進行訓練。
        
self.length = -1
       
# 分類的類別標籤
       
self.labelcount = dict()
       
self.vectorcount = dict()
   
# 訓練函式:(dataSet:list 訓練集指定為list型別)
   
def fit(self, dataSet:list, labels:list):
       
if(len(dataSet)!=len(labels)):
           
raise ValueError("您輸入的測試陣列跟類別陣列長度不一致~")
       
self.length = len(dataSet[0]) # 測試資料特徵值的長度。
       
# 所有類別的資料
       
labelsnum = len(labels)
       
# 不重複的類別的數量
       
norepeatlabel = set(labels)
       
# 以此遍歷各個類別
       
for item in norepeatlabel:
           
# 計算當前類別佔總類別的比例:
           
# thislabel為當前類別
           
thislabel = item
           
# 當前類別在總類別中的比例;
           
labelcount[thislabel]= labels.count(thislabel)/labelsnum
       
for vector, label in zip(dataSet, labels):
           
if(label not in vectorcount):
               
self.vectorcount[label]= []
           
self.vectorcount[label].append(vector)
       
print("訓練結束~")
       
return self
   
# 測試資料:
   
def btest(self, TestData, labelsSet):
       
if(self, length==-1):
           
raise ValueError("您還沒有進行訓練,請先訓練~~")
       
# 計算testdata分別為各個類別的概率:
       
lbDict = dict()
       
for thislb in labelsSet:
            p =
1
           
# 當前類別佔總類別的比例:
           
alllabel = self.labelcount[thislb]
           
# 當前類別中的所有向量:
           
allvector = self.vectorcount[thislb]
           
# 當前類別一共有多少個向量:
           
vnum = len(allvector)
           
# 陣列轉置
           
allvector =npy.array(allvector).T
           
for index in range(0, len(TestData)):
                vector =
list(allvector[index])
                p* = vector.count(TestData[index])/vnum
            lbDict[thislb] = p*alllabel
        thislabel =
sorted(lbDict, key=lambda x:lbDict[x], reverse=True)[0]
       
return thislabel

5、KNN手寫體數字識別:

此處使用畫圖工具,建立一個含手寫體數字的圖片檔案,然後找一些訓練資料:

1)訓練資料:

0、1、2、3、4、5、6、7、8、9,共十種手寫體資料,用來訓練程式,此處使用trainDigits;

2)測試資料:

即將之前的圖片轉換成的txt檔案作為測試檔案,此處使用testDigits;

3)圖片處理:

在進行二維碼或者圖片數字識別時,需要將圖片轉換成txt的二進位制檔案,行程一個檔案流。

KNN演算法的主要思路為:

1)計算輸入點與訓練集中點的位置(歐式距離演算法);

2)對計算出來的資料按照從小到大排序,最前面的為輸入點到訓練集中點的最短距離;

3)取出前k個距離值,並對距離值進行分組;

4)標記各組資料的多少,最多的標籤值即為輸入點的所在類別。

#!/usr/bin/env python

# _*_ UTF-8 _*_

from PIL import Image
from numpy import *
import operator
from os import listdir

# # 圖片處理
# # 先將所有圖片轉換為固定寬高,比如:32*32,然後再轉換成文字。
# im = Image.open("F:/python_workspace/file/hand_write/hand_write.png")
# #
另存為圖片:
# #im.save("F:/python_workspace/file/hand_write/hand_write.jpg")
# fh =open("F:/python_workspace/file/hand_write/hand_write.txt","a")
# #
獲取圖片的長寬高: 0:寬;1:高;
# width = im.size[0]
# height = im.size[1]
# #
獲取畫素(寬為1,高為9的畫素)
# # (255, 255, 255):白色
# # (0,0,0):黑色
# for i in range(0, width):
#     for j in range(0, height):
#         cl = im.getpixel((i, j))
#         clall = cl[0]+cl[1]+cl[2]
#         if(clall == 0):
#             #
黑色;
#             fh.write("1")
#         else:
#             fh.write("0")
#     fh.write("\n")
# fh.close()

#
運算knn函式:
def knn(k, testdata, traindata, labels):
    traindatasize = traindata.shape[
0]
    dif = tile(testdata
, (traindatasize, 1))-traindata
    sqdif = dif**
2
   
sumsqdif =sqdif.sum(axis=1)
    distance = sumsqdif**
0.5
   
sortdistance =distance.argsort()
    count = {}
   
for i in range(0, k):
        vote = labels[sortdistance[i]]
        count[vote] = count.get(vote
, 0)+1
   
sortcount = sorted(count.items(), key=operator.itemgetter(1), reverse=True)
   
return sortcount[0][0]

# 手寫體數字的識別:
# 1.載入資料
def datatoarray(fname):
    arr = []
    fh =
open(fname)
   
for i in range(0, 32):
        thisline = fh.readline()
       
for j in range(0, 32):
            arr.append(
int(thisline[j]))
   
return arr
# arr1 = datatoarray("F:/python_workspace/file/hand_write/trainingDigits/0_10.txt")
# print(arr1)

#
建立一個函式取檔案的字首:
def seplabel(fname):
    filestr = fname.split(
".")[0]
    label =
int(filestr.split("_")[0])
   
return label

# 2.建立訓練資料:
def traindata():
    labels = []
   
# 載入當前目錄下的所有檔名:
   
trainfile =listdir("F:/python_workspace/file/hand_write/trainingDigits")
    num =
len(trainfile)
   
# 長度為1024,即為1024列,每一行儲存一個檔案。
   
# 用一個數組儲存所有訓練資料,行:檔案總數;列:1024
    #
zeros建立一個數組:
   
trainarr =zeros((num, 1024))
   
for i in range(0, num):
        thisfname = trainfile[i]
       
# 返回的是訓練數字labels(0--9)
       
thislabel =seplabel(thisfname)
        labels.append(thislabel)
       
# 將所有檔案的訓練集資料內容載入到trainarr中。
       
trainarr[i, :] =datatoarray("F:/python_workspace/file/hand_write/trainingDigits/"+thisfname)
   
return trainarr, labels

# 3.用測試資料呼叫knn演算法測試,看是否能夠準確識別:
def datatest():
    trainarr
, labels =traindata()
    testlist = listdir(
"F:/python_workspace/file/hand_write/testDigits")
    tnum =
len(testlist)
   
for i in range(0, tnum):
        thistestfile = testlist[i]
        testarr = datatoarray(
"F:/python_workspace/file/hand_write/testDigits/"+thistestfile)
        rknn = knn(
3, testarr, trainarr, labels)
       
print(rknn)

datatest()

# 4.抽某一個測試檔案出來進行試驗:
trainarr, labels = traindata()
thistestfile =
"6_6.txt"
testarr = datatoarray("F:/python_workspace/file/hand_write/testDigits/"+thistestfile)
rknn = knn(
3, testarr, trainarr, labels)
print(rknn)

6、貝葉斯手寫體數字識別:

#!/usr/bin/env python

# _*_ UTF-8 _*_
import numpy as npy
from numpy import *
from os import listdir
# 貝葉斯演算法的應用:

class Bayes:
   
def __init__(self):
       
# -1表示測試方法沒有做,表示沒有進行訓練。
       
self.length = -1
       
# 分類的類別標籤
       
self.labelcount = dict()
       
self.vectorcount = dict()
   
# 訓練函式:(dataSet:list  訓練集指定為list型別)
   
def fit(self, dataSet:list, labels:list):
       
if(len(dataSet)!=len(labels)):
           
raise ValueError("您輸入的測試陣列跟類別陣列長度不一致~")
       
self.length = len(dataSet[0]) # 測試資料特徵值的長度。
       
# 所有類別的資料
       
labelsnum = len(labels)
       
# 不重複的類別的數量
       
norepeatlabel = set(labels)
       
# 以此遍歷各個類別
       
for item in norepeatlabel:
           
# 計算當前類別佔總類別的比例:
           
# thislabel為當前類別
           
thislabel = item
           
# 當前類別在總類別中的比例;
           
self.labelcount[thislabel]= labels.count(thislabel)/labelsnum
       
for vector, label in zip(dataSet, labels):
           
if(label not in self.vectorcount):
               
self.vectorcount[label]= []
           
self.vectorcount[label].append(vector)
       
print("訓練結束~")
       
return self
   
# 測試資料:
   
def btest(self, TestData, labelsSet):
       
if(self.length==-1):
           
raise ValueError("您還沒有進行訓練,請先訓練~~")
       
# 計算testdata分別為各個類別的概率:
       
lbDict = dict()
       
for thislb in labelsSet:
            p =
1
           
# 當前類別佔總類別的比例:
           
alllabel = self.labelcount[thislb]
           
# 當前類別中的所有向量:
           
allvector = self.vectorcount[thislb]
           
# 當前類別一共有多少個向量:
           
vnum = len(allvector)
           
# 陣列轉置
           
allvector =npy.array(allvector).T
           
for index in range(0, len(TestData)):
                vector =
list(allvector[index])
                p = vector.count(TestData[index])/vnum
            lbDict[thislb] = p*alllabel
        thislabel =
sorted(lbDict, key=lambda x:lbDict[x], reverse=True)[0]
       
return thislabel

# 手寫體數字的識別:
# 1.載入資料
def datatoarray(fname):
    arr = []
    fh =
open(fname)
   
for i in range(0, 32):
        thisline = fh.readline()
       
for j in range(0, 32):
            arr.append(
int(thisline[j]))
   
return arr

# 建立一個函式取檔案的字首:
def seplabel(fname):
    filestr = fname.split(
".")[0]
    label =
int(filestr.split("_")[0])
   
return label

# 2.建立訓練資料:
def traindata():
    labels = []
   
# 載入當前目錄下的所有檔名:
   
trainfile =listdir("F:/python_workspace/file/hand_write/trainingDigits")
    num =
len(trainfile)
   
# 長度為1024,即為1024列,每一行儲存一個檔案。
   
# 用一個數組儲存所有訓練資料,行:檔案總數;列:1024
    #
zeros建立一個數組