離散與連續
數據–數據對象、樣本、實例
離散屬性–類別屬性
- 用名稱標註
- 用類別/類別號來標註
連續屬性–連續的小數
- 在一個區間內連續,用浮點型數值表示
數據集
多個數據組合在一起–數據集合–數據集
- 行:代表樣本
- 列:代表屬性
一、機器學習
(一)概念
在歷史數據中發現規律,然後利用規律,對新的數據進行預測與指導。
(二)數據分析與數據挖掘
人工智能的基礎
想要一個好的機器學習結果,就必須有一個好的數據處理。
數據分析與數據挖掘的區別
數據分析主要偏向於業務。
數據挖掘主要偏向於對數據價值的挖掘。
(三)按照學習方式分類
1.監督學習
數據:既有特徵值,又有目標值
研究:研究的是特徵與目標之間的關係
數據集
訓練集與測試集的劃分
算法代表
1.分類算法:目標值是離散的
(1)KNN算法
特點
- k值不同,分類的結果不同
- 需要將所有的數據,加載到內存,不斷計算每一個測試樣本與訓練樣本的距離。時間、空間消耗比較大。
- 惰性學習算法
優化
(2)貝葉斯算法
2.迴歸算法:目標值是連續的
2.無監督學習
數據:只有特徵值,無目標值數據
研究:研究的是樣本和樣本之間的關係
數據集
不需要劃分
算法代表
1.聚類算法–K-Means算法
利用樣本的特徵,使最終的結果,同一類別內的樣本具有較高的相似性,不同類別的樣本具有較高的相異性。
3.半監督學習
隱馬爾可夫模型
二、K-Means
應用場景
用於用戶羣體的劃分。
(一)k-means原理自實現
# 科學計算庫
import numpy as np
# 數據可視化庫
import matplotlib.pyplot as plt
# 數據處理庫
import pandas as pd
def bulid_data():
'''
構建數據
:return:數據
'''
# 加載數據
# 1.open
# 2.np.loadtxt/np.genfromtxt -- 文本類型的數組
# 3.pd.read_table
# sep和delimiter都可以指定分隔符
# header=None -- 不讓它將第一行設爲行標
data = pd.read_table('test.txt',sep='\t',header=None)
# 轉化爲矩陣(矩陣--特殊的數組)
# mat = asmatrix
# matrix -- 比mat多了一個拷貝內存的過程
# bmat -- 組合矩陣
data = np.mat(data.values)
return data
def center_init(data,k):
'''
聚類中心初始化
:param data: 數據
:param k: 聚類的類別數目
:return: center
'''
# 確定數據的行下標範圍
index_num = data.shape[0]
# 確定數據的列數
column_num = data.shape[1]
# 使用全零數組爲聚類中心佔位
center = np.zeros((k,column_num))
# 隨機選擇所有樣本中的k個樣本作爲最開始的聚類中心
# 計數器
i = 0
# 避免重複
r_list = []
while True:
r = np.random.randint(0,index_num-1)
if r in r_list:
continue
else:
r_list.append(r)
center[i,:] = data[r,:]
i+=1
if len(r_list) == k:
break
return center
def distance(v1,v2):
'''
距離計算
:param v1: 點1
:param v2: 點2
:return: 距離
'''
# # 方法1
# sum_ = 0
# # v1.shape -- 二維
# # v2.shape -- 一維
# # 將v1由2維降爲1維
# # 將矩陣轉換爲數組:使用矩陣視圖
# # 矩陣.A --> 數組
# v1 = v1.A[0]
# if v1.shape == v2.shape:
# for i in range(len(v1)):
# sum_ += (v1[i] - v2[i])**2
# return np.sqrt(sum_)
# 方法2
diff = v1 - v2
d = np.sqrt(np.sum(np.power(diff,2)))
return d
def k_means_owns(data,k):
'''
自實現k-means原理
:param data: 數據
:param k: 聚類的類別數目
:return: 各個樣本最終的類別,最終的聚類中心
'''
# 初始化聚類中心--隨機初始化
# 隨機在所有樣本中選取k個聚類中心
center = center_init(data,k)
# 數據行數
index_num = data.shape[0]
# 定義數組,保存距離樣本最近的聚類中心及距離
new_data = np.zeros((index_num,2))
flag = True
while flag:
flag = False
# 計算每一個訓練樣本與聚類中心的距離
# 雙層循環----外層 -- 訓練樣本
# 內層 -- 聚類中心
for i in range(index_num):
min_dist = 10000000000000000000
min_index = -1
for j in range(k):
# 計算距離
# 高緯度的數組使用下標,會進行降維度
# 矩陣是二維的特殊數組,使用索引不會降維度
d = distance(data[i, :], center[j, :])
# print(d)
if d < min_dist:
min_dist = d
min_index = j
# 如果當前的樣本屬於的簇與上一次的不一致
if new_data[i,0] != min_index:
new_data[i:] = min_index, min_dist
flag = True
if flag:
# 計算新的聚類中心
# 計算每一簇的均值 -- 每一簇的中心
# 使用bool數組索引
for p in range(k):
bool_index = new_data[:, 0] == p
# 選定簇
p_cluster = data[bool_index, :]
# 新的聚類中心
center[p, :] = p_cluster[:, 0].mean(), p_cluster[:, 1].mean()
# 如果新的聚類中心,與上一次的聚類中心重合--結束
# 改變思路:如果所有樣本所屬的聚類中心,與上一次所屬的聚類中心相同--結束
return new_data,center
def show_res_owns(data,new_data,center):
'''
結果展示
:param data: 原始數據
:param new_data: 保存着各個樣本最終的類別
:param center: 最終的聚類中心
:return: None
'''
# 1.創建畫布
plt.figure()
# 顯示中文,支持負號
plt.rcParams['font.sans-serif'] = 'SimHei'
plt.rcParams['axes.unicode_minus'] = False
# 2.繪圖
# 設置顏色列表
c_list = ['b','g','y','pink']
# 設置點形狀列表
marker_list = ['*','o','^','D']
# 繪製散點圖
for i in range(data.shape[0]):
plt.scatter(data[i,0],data[i,1],c=c_list[int(new_data[i,0])],marker=marker_list[int(new_data[i,0])])
# 繪製聚類中心
plt.plot(center[:,0],center[:,1],'bx',markersize=12)
# 增加名稱
plt.title('聚類結果展示')
# 保存圖片
plt.savefig('聚類結果展示')
# 3.繪圖展示
plt.show()
def main():
# 1.構建數據
data = bulid_data()
# print(data)
# print(type(data))
# print(data.dtype)
# 2.自實現k-means算法原理
# 確定聚類的類別數目
k = 4
new_data,center = k_means_owns(data,k)
# 3.結果展示
show_res_owns(data,new_data,center)
if __name__ == '__main__':
main()
(二)使用sklearn
# 科學計算庫
import numpy as np
# 數據可視化庫
import matplotlib.pyplot as plt
# 數據處理庫
import pandas as pd
from sklearn.cluster import KMeans
def bulid_data():
'''
構建數據
:return:數據
'''
# 加載數據
# 1.open
# 2.np.loadtxt/np.genfromtxt -- 文本類型的數組
# 3.pd.read_table
# sep和delimiter都可以指定分隔符
# header=None -- 不讓它將第一行設爲行標
data = pd.read_table('test.txt',sep='\t',header=None)
# 轉化爲矩陣(矩陣--特殊的數組)
# mat = asmatrix
# matrix -- 比mat多了一個拷貝內存的過程
# bmat -- 組合矩陣
data = np.mat(data.values)
return data
def show_res(data,y_predict,center):
'''
結果展示
:param data: 原始數據
:param y_predict:預測類別
:param center: 聚類中心
:return: None
'''
# 1.創建畫布
plt.figure()
# 顯示中文,支持負號
plt.rcParams['font.sans-serif'] = 'SimHei'
plt.rcParams['axes.unicode_minus'] = False
# 2.繪圖
# 設置顏色列表
c_list = ['b','g','y','pink']
# 設置點形狀列表
marker_list = ['*','o','^','D']
# 繪製散點圖
for i in range(data.shape[0]):
plt.scatter(data[i,0],data[i,1],c=c_list[y_predict[i]],marker=marker_list[y_predict[i]])
# 繪製聚類中心
plt.plot(center[:,0],center[:,1],'bx',markersize=12)
# 增加名稱
plt.title('聚類結果展示')
# 保存圖片
plt.savefig('聚類結果展示')
# 3.繪圖展示
plt.show()
def main():
# 1.構建數據
data = bulid_data()
# 2.使用sklearn中的KMeans進行聚類分析
# 確定聚類的類別數目
k = 4
# (1)構建算法實力
# n_clusters--指定聚類的類別
km = KMeans(n_clusters=k)
# init='k-means++'--以一種更優的方式選取初始聚類中心
# (2)進行訓練數據
km.fit(data)
# (3)驗證模型的好壞,即得到預測值
y_predict = km.predict(data)
# k-means算法--得到聚類中心
center = km.cluster_centers_
print('預測類別:\n',y_predict)
print('聚類中心:\n',center)
# 3.結果可視化
show_res(data,y_predict,center)
if __name__ == '__main__':
main()
(三)實例–NBA球星(sklearn)
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
def show_res(data,y_predict,center):
'''
結果展示
:param data: 原始數據
:param y_predict:預測類別
:param center: 聚類中心
:return: None
'''
# 1.創建畫布
plt.figure()
# 顯示中文,支持負號
plt.rcParams['font.sans-serif'] = 'SimHei'
plt.rcParams['axes.unicode_minus'] = False
# 2.繪圖
# 設置顏色列表
c_list = ['b','g','y','pink','red']
# 設置點形狀列表
marker_list = ['*','o','^','D','8']
# 繪製散點圖
for i in range(data.shape[0]):
plt.scatter(data[i,0],data[i,1],c=c_list[y_predict[i]],marker=marker_list[y_predict[i]])
# 繪製聚類中心
plt.plot(center[:,0],center[:,1],'bx',markersize=12)
# 增加名稱
plt.title('NBA球星聚類結果展示')
# 保存圖片
plt.savefig('NBA球星聚類結果展示')
# 3.繪圖展示
plt.show()
def build_data(data):
'''
數據預處理
:return:預處理後的數據
'''
# 2.數據合併
# 只有一個表
# 3.數據清洗
# (1)檢測與處理缺失值
# 檢測:pd.inull().sum()
# 處理:刪除值、填充法、插值法
# 處理非NaN類型缺失值,先將這種數據轉化爲np.NaN類型,再進行處理
# res_null = pd.isnull(data).sum()
# print(res_null) # 無缺失值
# (2)處理異常值
# 3sigma原理、箱線圖分析法
# 無異常值
# 4.篩選有用的特徵
data = data.loc[:, ['時間', '助攻', '得分']]
# print(data.dtypes)
# 時間 object
# 助攻 float64
# 得分 float64
# 將時間這一列的空格缺失值,轉換成np.NaN類型
data.loc[:, '時間'].replace(' ', np.NaN, inplace=True)
# res_null = pd.isnull(data).sum()
# print(res_null) # 時間列有393個空值
# 處理缺失值
# 使用上一個鄰居來填充缺失值
data.loc[:'時間'].fillna(method='pad', inplace=True)
# res_null = pd.isnull(data).sum()
# print(res_null) # 無空值
# 將時間的數據類型轉化爲float類型
data.loc[:, '時間'] = data.loc[:, '時間'].astype(np.float64)
# print(data.dtypes)
# 構建最終的得分/分鐘 助攻/分鐘
data.loc[:, '得分/分鐘'] = data.loc[:, '得分'] / data.loc[:, '時間']
data.loc[:, '助攻/分鐘'] = data.loc[:, '助攻'] / data.loc[:, '時間']
data = data.loc[:, ['得分/分鐘', '助攻/分鐘']]
return data
def main():
# 1.加載、構建數據
data = pd.read_excel('nba_data.xlsx')
# print(data)
# print(data.columns)
data = build_data(data)
# [5].標準化?
# 做數據分析時,暫時不要做;要進行機器學習算法構建模型的時候,必須要做
# 無需消除量綱
# [6].構建模型--算法模型--進行訓練數據--進行預測
# 確定聚類類別數量
k = 5
# 創建算法實例
km = KMeans(n_clusters=k)
# 訓練數據
km.fit(data.values)
# 進行預測
y_predict = km.predict(data.values)
# 預測中心
center = km.cluster_centers_
print('預測值:\n',y_predict)
print('聚類中心:\n',center)
# 7.數據可視化--折線圖、散點圖、直方圖、柱狀圖、餅圖、箱線圖
show_res(data.values,y_predict,center)
# 8.結論
if __name__ == '__main__':
main()
三、補充
(一)3sigma
異常值處理之3sigma
import pandas as pd
# 3sigma原則
# [mean-3*std,mean+s*std]
# 99.73%的數據
def three_sigma(data):
'''
進行3sigma異常值處理
:param data: 需要進行處理的數據--series
:return: bool數組
'''
# 下限
low = data.mean() - 3*data.std()
up = data.mean() + 3*data.std()
# 正常--True,異常--False
bool_index = (low <= data) & (data <= up)
return bool_index
# 驗證異常值處理
detail = pd.read_excel('meal_order_detail.xlsx')
# print(detail)
# print(detail.columns)
print(detail.shape[0])
# 對菜品的單價數據進行異常值剔除
bool_index = three_sigma(detail.loc[:, "amounts"])
detail = detail.loc[bool_index,:]
# print('按照菜品單價剔除異常值之後的結果\n',detail)
print(detail.shape[0])
(二)標準化
量級相差過大,就需要進行標準化
1.離差標準化
x = (x-min)/(max-min)
2.標準差標準化(推薦)
x = (x-mean)/std
3.小數定標標準化
通過移動數據的小數點位置來進行標準化。
k --> int(np.ceil(np.log10(|x|.max())))
x = x/10^k
(三)維度
行的方向是行增大的方向,即向下
列的方向是列增大的方向,即向右
1.一維
shape:(9,)
一維的數組只有列維度
axis=0,axis=-1 – 代表列維度
2.二維(多個一維組成)
shape:(2,3)
行列維度
axis=0,axis=-2 – 代表行維度
axis=1,axis=-1 – 代表列維度
3.三維(多個二維組成)
shape:(1,2,3)
塊行列維度
axis=0 – 代表塊維度
axis=1 – 代表行維度
axis=2 – 代表列維度
4.四維(多個三維組成)
shape:(1,2,3,4)
堆塊行列維度
……
……
mean()默認維度測試
import numpy as np
import pandas as pd
df = pd.DataFrame(data=np.array([[1,2,5],[1,3,4],[4,4,5]]))
print(df)
print(df.mean())
# 0 1 2
# 0 1 2 5
# 1 1 3 4
# 2 4 4 5
# 0 2.000000
# 1 3.000000
# 2 4.666667
# dtype: float64
發現最終的結果,求的是一列的平均值,即行增大的方向,也就是按行的方向求的。
即mean()默認的axis=0。
四、作業
- 將NBA實例的sklearn實現改爲自實現
- 超市用戶聚類案例
(一)NBA–自實現
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
def bulid_data(data):
data = data.loc[:,['時間','助攻','得分']]
# res_null = pd.isnull(data).sum()
# print(res_null)
data.loc[:,'時間'].replace(' ',np.NaN,inplace=True)
data.loc[:,'時間'].fillna(method='pad',inplace=True)
data.loc[:'時間'] = data.loc[:'時間'].astype(np.float64)
data.loc[:,'助攻/時間'] = data.loc[:,'助攻']/data.loc[:,'時間']
data.loc[:,'得分/時間'] = data.loc[:,'得分']/data.loc[:,'時間']
data = data.loc[:,['得分/時間','助攻/時間']]
return np.mat(data.values)
def center_init(data,k):
index_num = data.shape[0]
column_num = data.shape[1]
# print(index_num)
center = np.zeros((k,column_num))
r_list = []
i = 0
while True:
r = np.random.randint(0,index_num-1)
if r in r_list:
continue
else:
r_list.append(r)
center[i,:] = data[r,:]
i += 1
if len(r_list) == k:
break
return center
def distance(v1,v2):
diff = v1-v2
return np.sqrt(np.sum(np.power(diff,2)))
def k_means_owns(data,k):
# 隨機選取k個聚類中心
center = center_init(data,k)
index_num = data.shape[0]
new_data = np.zeros((index_num,2))
flag = True
while flag:
flag = False
for i in range(index_num):
min_distence = 1000000000000000
min_index = -1
for j in range(k):
# 計算距離聚類中心距離
d = distance(data[i,:],center[j,:])
if d < min_distence:
min_distence = d
min_index = j
if new_data[i,0] != min_index:
flag = True
new_data[i,:] = min_index,min_distence
if flag:
# 計算新的聚類中心
for p in range(k):
bool_index = new_data[:,0] == p
p_cluster = data[bool_index,:]
center[p,:] = p_cluster[:,0].mean(),p_cluster[:,1].mean()
return new_data,center
def show_res(data,new_data,center):
plt.figure()
plt.rcParams['font.sans-serif'] = 'SimHei'
plt.rcParams['axes.unicode_minus'] = False
c_list = ['c','g','y','pink','red']
marker_list = ['*','o','^','D','8']
# 繪製樣本數據
for i in range(data.shape[0]):
plt.scatter(data[i,0],data[i,1],c=c_list[int(new_data[i,0])],marker=marker_list[int(new_data[i,0])])
# 繪製聚類中心
plt.plot(center[:, 0], center[:, 1], 'bx', markersize=12)
plt.title('NBA球星聚類分析結果')
plt.savefig('NBA球星聚類分析結果')
plt.show()
def main():
# 讀取數據
data = pd.read_excel('../03.實例:基於k_means算法實現NBA球員聚類分析/nba_data.xlsx')
# print(data)
# 構建數據
data = bulid_data(data)
# k-means自實現
# 確定聚類中心個數
k = 5
new_data,center = k_means_owns(data, k)
show_res(data,new_data,center)
if __name__ == '__main__':
main()
(二)超市用戶–sklearn
import numpy as np
import pandas as pd
from sklearn.cluster import KMeans
import matplotlib.pyplot as plt
def stand_sca(data):
'''
標準差標準化
:param data:需要標準化的數據
:return:標準化後的數據
'''
data = (data-data.mean())/data.std()
return data
def min_max_sca(data):
'''
離差標準化
:param data: 需要標準化的數據
:return: 標準化後的數據
'''
data = (data-data.min(axis=0))/(data.max(axis=0)-data.min(axis=0))
return data
def desc_sca(data):
'''
小數定標標準化
:param data: 需要標準化的數據
:return: 標準化之後的數據
'''
k = int(np.ceil(np.log10(data.abs().max())))
data = data / (10**k)
return data
def build_data():
# 1.構建數據
data = pd.read_table('company.csv', sep=',', encoding='gbk')
# 2.篩選特徵值
data = data.loc[:,['平均每次消費金額','平均消費週期(天)']]
# 3.缺失值檢測
# res_null = pd.isnull(data).sum()
# print(res_null)
# 4.處理異常值
# 無異常值
# 5.標準化
# (1)標準差標準化
# data = stand_sca(data)
# (2)離差標準化
data = min_max_sca(data)
return np.mat(data.values)
def k_means(data):
# 確定聚類中心個數
k = 3
# 1.創建算法實例
km = KMeans(n_clusters=k)
# 2.訓練數據
km.fit(data)
# 3.進行預測
y_predict = km.predict(data)
# 獲取聚類中心
center = km.cluster_centers_
# print('預測值:\n',y_predict)
# print('聚類中心:\n',center)
return y_predict,center
def show(data,y_predict,center):
plt.figure()
plt.rcParams['font.sans-serif'] = 'SimHei'
plt.rcParams['axes.unicode_minus'] = False
c_list = ['pink','yellow','green','blue']
marker_list = ['*','>','^','o']
for i in range(data.shape[0]):
plt.scatter(data[i,0],data[i,1],c=c_list[y_predict[i]],marker=marker_list[y_predict[i]])
plt.plot(center[:,0],center[:,1],'bx',markersize=12)
plt.title('超市用戶聚類結果')
plt.savefig('超市用戶聚類結果')
plt.show()
def main():
data = build_data()
# print(data)
y_predict,center = k_means(data)
show(data,y_predict,center)
if __name__ == '__main__':
main()
(三)超市用戶–自實現
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
def stand_sca(data):
'''
標準差標準化
'''
data = (data - data.mean())/data.std()
return data
def min_max_sca(data):
'''
離差標準化
'''
data = (data - data.min())/(data.max()-data.min())
return data
def build_data():
# 獲取數據
data = pd.read_table('company.csv', sep=',', encoding='gbk')
# 獲取有效數據
data = data.loc[:,['平均每次消費金額','平均消費週期(天)']]
# 檢測缺失值
# res_null = pd.isnull(data).sum()
# print(res_null)
# 檢測異常值
# 無異常值
# 標準化
data = min_max_sca(data)
return np.mat(data.values)
def center_init(data,k):
index_num = data.shape[0]
center = np.zeros((k,data.shape[1]))
r_list = []
i = 0
while True:
r = np.random.randint(0,index_num-1)
if r in r_list:
continue
else:
center[i,:] = data[r,:]
r_list.append(r)
i += 1
if len(r_list) == k:
break
return center
def distance(v1,v2):
diff = v1-v2
d = np.sqrt(np.sum(np.power(diff,2)))
return d
def k_means_owns(data,k):
center = center_init(data,k)
# print(center)
index_num = data.shape[0]
column_num = data.shape[1]
new_data = np.zeros((index_num,column_num))
for i in range(index_num):
min_dis = 1000000000000
min_index = -1
for j in range(k):
d = distance(data[i,:],center[j,:])
if d < min_dis:
min_dis = d
min_index = j
new_data[i,:] = min_index,min_dis
for p in range(k):
bool_index = new_data[:,0] == p
p_cluster = data[bool_index,:]
center[p,:] = p_cluster[:,0].mean(),p_cluster[:,1].mean()
return new_data,center
def show(data,new_data,center):
plt.figure()
plt.rcParams['font.sans-serif'] = 'SimHei'
plt.rcParams['axes.unicode_minus'] = False
c_list = ['pink','yellow','green','blue']
marker_list = ['*','>','^','o']
for i in range(data.shape[0]):
plt.scatter(data[i,0],data[i,1],c=c_list[int(new_data[i,0])],marker=marker_list[int(new_data[i,0])])
plt.plot(center[:,0],center[:,1],'bx',markersize=12)
plt.title('超市用戶聚類結果')
plt.savefig('超市用戶聚類結果')
plt.show()
def main():
data = build_data()
print(data)
k = 3
new_data,center = k_means_owns(data,k)
show(data,new_data,center)
if __name__ == '__main__':
main()