⑴ python購物籃數據(關聯分析)
pip install mlxtend
由於已經是csv格式,所以直接輸入:
每一行: 一個購物籃
每一列: 購物籃中的商品
先看看pd讀的對不對:
然後按行列印:
再將這些存在一個數組中:
1、什麼是獨熱碼
獨熱碼,在英文文獻中稱做 one-hot code, 直觀來說就是有多少個狀態就有多少比特,而且只有一個比特為1,其他全為0的一種碼制,更加詳細參加 one_hot code(維基網路) 。在機器學習中對於離散型的分類型的數據,需要對其進行數字化比如說性別這一屬性,只能有男性或者女性或者其他這三種值,如何對這三個值進行數字化表達?一種簡單的方式就是男性為0,女性為1,其他為2,這樣做有什麼問題?
使用上面簡單的序列對分類值進行表示後,進行模型訓練時可能會產生一個問題就是特徵的因為數字值得不同影響模型的訓練效果,在模型訓練的過程中不同的值使得同一特徵在樣本中的權重可能發生變化,假如直接編碼成1000,是不是比編碼成1對模型的的影響更大。為了解決上述的問題,使訓練過程中不受到因為分類值表示的問題對模型產生的負面影響,引入獨熱碼對分類型的特徵進行獨熱碼編碼。
可以這樣理解,對於每一個特徵,如果它有m個可能值,那麼經過獨熱編碼後,就變成了m個二元特徵(如成績這個特徵有好,中,差變成one-hot就是100, 010, 001)。並且,這些 特徵互斥 ,每次只有一個激活。因此,數據會變成稀疏的。
這樣做的好處主要有:
(1)解決了分類器不好處理 屬性數據 的問題
(2)在一定程度上也起到了 擴充特徵 的作用
M
以下為我摘取的別人的,貼上原文鏈接https://blog.csdn.net/hellozhxy/article/details/80600845
著名的啤酒與尿布, 這是典型的購物籃問題, 在數據挖掘界叫做頻繁項集(Frequent Itemsets).
note: 數據類型寫法按照Python的格式.
一. 目標與定義
1. 問題背景
超市中購物清單中總是有一些項目是被消費者一同購買的. 如果我們能夠發現這些 關聯規則 (association rules), 並合理地加以利用, 我們就能取得一定成果. 比如我們發現熱狗和芥末存在這種關系, 我們對熱狗降價促銷, 而對芥末適當提價, 結果能顯著提高超市的銷售額.
2. 目標
找到頻繁地 共同 出現在消費者結賬小票中項目(比如啤酒和尿布), 來一同促銷, 相互拉動, 提高銷售額.
3. 定義
支持度support: 其實就是概率論中的頻次frequency
支持度閾值support threshhold: 記為s, 指分辨頻繁項集的臨界值.
頻繁項集: 如果I是一個項集(Itemset), 且I的出現頻次(i.e.支持度)大於等於s, 那麼我們說I是頻繁項集.
一元項, 二元項, 三元項: 包含有一種商品, 兩種, 三種商品的項集.
4. 關聯規則
關聯規則: 形式為I->j, 含義是如果I種所有項都出現在某個購物籃的話, 那麼j很有可能也出現在這個購物籃中. 我們可以給出相應的confidence值(可信度, 即概率論中的置信度).
其中, 這個關聯規則的可信度計算為Confidence = I∪{j} / I, 本身是非常符合直覺和常識的. 比如我們說關聯規則{dog, cat} -> and 的可信度為0.6, 因為{dog, cat}出現在了1, 2, 3, 6, 7五個購物籃中, 而and出現在了1,2,7中, 因此我們可以算出Confidence = freq[{dog, cat, and}] / freq[{dog, cat}] = 3/5 = 0.6
注意到, 分子部分的頻次總是比分母低, 這是因為{dog, cat} 出現的次數總是大於等於{dog, cat, and}的出現次數.
二. 購物籃與A-Priori演算法
1. 購物籃數據表示
我們將有一個文本文件輸入, 比如allBills.txt, 或者allBills.csv. 裡面每行是一個購物籃.
文件的頭兩行可能是這樣(df.show(2)):
{23, 456, 1001}
{3, 18, 92, 145}
我們假定這是一家大型連鎖超市, 比如沃爾瑪, 因此這個文本文件是非常大的, 比如20GB. 因此我們無法一次將該文件讀入內存. 因此, 演算法的主要時間開銷都是磁碟IO.
我們同時還假定, 所有購物籃的平均規模是較小的, 因此在內存中產生所有大小項集的時間開銷會比讀入購物籃的時間少很多.
我們可以計算, 對於有n個項目組成的購物籃而言, 大小為k的所有子集的生成時間約為(n, k) = n! / ((n-k)!k!) = O(n^k/ k!), 其中我們只關注較小的頻繁項集, 因此我們約定k=2或者k=3. 因此所有子集生成時間T = O(n^3).
Again, 我們認為 在內存中產生所有大小項集的時間開銷會比讀入購物籃的時間少很多.
2. Itemset計數過程中的內存使用
我們必須要把整個k,v字典放在內存中, 否則來一個Itemset就去硬碟讀取一次字典將十分十分地慢.
此處, 字典是k=(18, 145), v=15這種形式. 此處, 應當注意到, 如果有{bread, milk, orange}這樣的String類型輸入, 應當預先用一個字典映射成對應的整數值編碼, 比如1920, 4453, 9101這樣.
那麼, 我們最多能用字典存儲多少種商品?
先看下我們存儲多少個count值.
我們假定項的總數目是n, 即超市有n種商品, 每個商品都有一個數字編號, 那麼我們需要(n, 2) = n^2/2 的大小來存儲所有的二元組合的count, 假設int是佔4個byte, 那麼需要(2·n^2)Byte內存. 已知2GB內存 = 2^31 Byte, 即2^31/2 = 2^30 >= n^2 --> n <= 2^15. 也就是說n<33 000, 因此我們說商品種類的最多是33k種.
但是, 這種計算方法存在一個問題, 並不是有10種商品, 那麼這10種商品的任意二元組合都會出現的. 對於那些沒出現的組合, 我們在字典中完全可以不存儲, 從而節省空間.
同時, 別忘了我們同樣也得存儲key = (i, j), 這是至少額外的兩個整數.
那麼我們到底具體怎麼存儲這些計數值?
可以採用三元組的方式來構造字典. 我們採用[i, j, count]形式來存儲, 其中i代表商品種類1, j代表商品種類2, 前兩個值代表key, 後面的value就是count, 是這個二元組合下的計數.
現在, 讓我們注意到我們(1)假定購物籃平均大小較小, 並(2)利用三元組(2個key的)字典和(3)不存儲沒出現組合優勢. 假設有100k = 10^5種商品, 有10million=10^7個購物籃, 每個購物籃有10個項, 那麼這種字典空間開銷是(10, 2) · 10^7 = 45 x 10^7 x 3= 4.5x10^8x3 = 1.35x10^9 個整數. 這算出來約為4x10^8 Byte = 400MB, 處於正常計算機內存范圍內.
3. 項集的單調性
如果項集I是頻繁的, 那麼它的所有子集也都是頻繁的. 這個道理很符合常識, 因為{dog, cat} 出現的次數總是大於等於{dog, cat, and}的出現次數.
這個規律的推論, 就是嚴格地, 我們頻繁一元組的個數> 頻繁二元組的個數 > 頻繁三元組的個數.
4. A-Priori演算法
我們通過Itemset計數中內存使用的部門, 已經明確了我們總是有足夠的內存用於所有存在的二元項集(比如{cat, dog})的計數. 這里, 我們的字典不存放不存在於購物籃中的任何二元項集合, 而且頻繁二元組的數目將會大於三元頻繁三元組> ...
我們可以通過單邊掃描購物籃文件, 對於每個購物籃, 我們使用一個雙重循環就可以生成所有的項對(即二元組). 每當我們生成一個項對, 就給其對應的字典中的value +1(也稱為計數器). 最後, 我們會檢查所有項對的計數結果,並且找出那些>=閾值s的項對, 他們就是頻繁項對.
1) A-Priori演算法的第一遍掃描
在第一遍掃描中, 我們將建立兩個表. 第一張表將項的名稱轉換為1到n之間的整數, 從而把String類型這樣的key轉為空間大小更小的int類型. 第二張表將記錄從1~n每個項在所有購物籃中出現的次數. 形式上類似
table 0(name table): {'dolphin': 7019, 'cat': 7020} //dict形式, 其實也可以做成list形式 [['dolphin', 7019], ['cat', 7020]]
table 1(single-item counter table): {7019: 15, 7020: 18} //dict形式, 其實也可以做成數組形式A[7019] = 2, A[7020] = 18
2) 第一遍掃描完的處理
第一遍掃描完後, 我們會按照自己設定的閾值s, 對整個table 1再進行一次mapping, 因為我們只關注最後counter值大於等於閾值的項目, 而且不關心其counter值具體多少. 因此, mapping策略是:
對凡是counter<s的, 一律把counter設成0; 對於counter>=s的, 按照次序, 把其設置成1~m的值(總共有m個滿足要求的項)
3) 第二遍掃描
第二遍掃描所做的事有三:
(1) 對每個購物籃, 在table 1中檢查其所有的商品項目, 把所有為頻繁項的留下來建立一個list.
(2) 通過一個雙重循環生成該list中的所有項對.
(3) 再走一次循環, 在新的數據結構table 2(dict或者list)中相應的位置+1. 此時的效果是dicta = {48: {13: 5}, 49: {71, 16}} 或者 lista [ [48, 13, 5],[49, 71, 16], ... ]
注意此時內存塊上存儲的結構: table1(name table), table2(single-item counter table), table3(double-item counter table)
5. 推廣: 任意大小頻繁項集上的A-Priori演算法
我們對上面這個演算法進行推廣.
從任意集合大小k到下一個大小k+1的轉移模式可以這么說:
(1) 對每個購物籃, 在table 1中檢查其所有的商品項目, 把所有為頻繁項的留下來建立一個list.
(2) 我們通過一個k+1重循環來生成該list中的所有(k+1)元組
(3) 對每個k+1元組, 我們生成其的(k+1 choose k)個k元組, 並檢查這些k元組是否都在之前的table k中. (注意到k=1的時候, 這步與(1)是重復的, 可以省略)
(4)再走一次循環, 在新的數據結構table k+1(dict或者list)中相應的位置+1. 此時的效果是k=2, k+1=3, 生成dicta = {48: {13: {19: 4}}, 49: {71: {51: 10}}, ... } 或者 生成lista [ [48, 13, 19, 4],[49, 71, 51, 10], ... ]
注意, 在進入下一次掃描前, 我們還需要額外把counter中值小於s的元組的計數值都記為0.
模式總體是:C1 過濾後 L1 計數後 C2 置零後 C2' 過濾後 L2 計數後 C3 置零後 C3' ......
END.
生成的商品種類為set形式:轉成list形式
第一張表:把項名稱轉換為1~n的整數:
至於數數,大神說,你就用collections.Counter就好:哈?
哈哈,可愛的wyy,開始分析吧~嚕嚕嚕啦啦啦~嚕啦嚕啦嚕~
生成全零矩陣:
換成zeros:
統計每一列的和,即每種商品的購買總數:
每一行列:
第一行:
建立一個新的只含有頻繁一項集的購物籃矩陣:
頻繁二項集:
⑵ 如何將py文件與python.exe關聯
安裝好python,建議將python安裝在根目錄下。
去cxfreeze官網下載好對應的cx_freeeze版本。
正確安裝cx_freeze,看下圖
運行:cmd命令,查看cx_freeze是否安裝正確。如果出現了下圖的情況,說明環境變數設置不正確。請點擊下面的環境變數設置方法。
0環境變數設置方法
當然,設置完環境變數可能還是有問題,那麼這里就要設置路徑了,路徑設置在cxfreeze.bat文件中,cxfreeze.bat文件在:c:\python34\scripts文件夾下(如果你不是安裝在c盤,找到相應位置即可)看下圖,這里發現沒有cxfreeze.bat文件。
那麼要怎麼生成cxfreeze.bat文件呢。用python編譯一下cxfreeze-postinstall(二進制)文件即可,編譯後的文件如下圖
用記事本打開cxfreeze.bat文件。如果你不是裝在c盤,請將路徑改成你的安裝路徑。
這里以經典的hello world為例,看下圖。cd: c:\python34\scripts將目錄轉到cxfreeze所在目錄。cxfreeze c:\test\hello.py --target-dir c:\test命令:cxfreeze c:\test\hello.py對hello.py進行編譯,--target-dir目標存儲目錄為c:\test文件夾。生成過程相當長,如下圖。
看下test文件夾下,已經生成.exe文件。
點擊運行,如下圖(如果沒有在代碼中添加暫停的代碼,只能看到黑框一閃而過)代碼在後面一張圖,供參考。至些,.py文件成功轉成.exe可執行文件。
⑶ python 關聯規則分前項後項嗎
學了兩天python,想實踐下,正好最近在學習數據挖掘,先用python實現下
註:由於後面加了注釋,由於編碼問題,可能即使是注釋,有的環境也不支持漢字的編碼,運行報錯的話可以將漢字刪除後再運行
環境 ubuntu 13.4 python 2
[python]view plain
importitertools
import
'''''
定義全局變數k,即支持度計數k,此k也可以在運行程序之前輸入,簡單改動即可
'''
k=2
'''''
存儲頻繁項集的列表
'''
frequenceItem=[]
'''''
從txt文件dataset.txt里獲取事務集
'''
defgetDataSet(args):
f=open(args,'r')
source=f.readlines()
f.close()
dataset=[]
forlineinsource:
temp1=line.strip(' ')
temp2=temp1.split(',')
dataset.append(temp2)
returndataset
'''''
初步掃描事務集,從事務集里獲取候選1項集
方法的基本思路是:
定義一個集合tmp,將事務集的第一項作為tmp的初始集合
然後掃描事務集,將不在tmp里的數據項加入tmp中
'''
deffind_item(dataset):
length=len(dataset)
foriinrange(0,length):
ifi==0:
tmp=set(dataset[i])
tmp.update(set(dataset[i]))
candidate=list(tmp)
candidate.sort()
returncandidate
'''''
從候選項集里找出頻繁項集,其中num代表頻繁num+1項集
如num為0的為從候選1項集里找出頻繁1項集
方法基本思路:
1、定義一個支持度列表count
2、對於每一個候選項,依次掃描事務集,如果該項出現在事務集中就將該項對應的count+1、定義一個支持度列表count+1
3、將每一項的count和k(支持度計數)進行比較,將count小於k的項剔除
'''
deffind_frequent(candidate,dataset,num):
frequence=[]
length=len(candidate)
count=[]
foriinrange(0,length):
count.append(0)
count[i]=0
ifnum==0:
'''''
其實不管num為0還是別的值演算法應該是一樣的,但是由於程序實現上的問題
num為0的時候選項集是一維列表,其它的時候,候選項集是二維列表,
畢竟只是自己寫著玩的,python還不熟,牽一發而動全身,懶得改了
'''
child=set([candidate[i]])
else:
child=set(candidate[i])
forjindataset:
parent=set(j)
ifchild.issubset(parent):
count[i]=count[i]+1
forminrange(0,length):
ifcount[m]>=k:
frequence.append(candidate[m])
returnfrequence
'''''
先驗定理,剪枝掉不必要的候選n項集
方法思路:
1、依次取出候選項集里的項
2、取出n項集里的n-1項子集
3、如果所有的n-1項集不都都是頻繁n-1項集的子集,則刪除該候選項集
'''
defpre_test(candidate,num,frequence):
r_candidate=.deep(candidate)
foreachincandidate:
foreach2initertools.combinations(each,num):
tmp=(list(each2))
tag=0
forjinfrequence:
ifnum==1:
if(tmp[0]==j):
tag=1
break
else:
iftmp==j:
tag=1
break
iftag==0:
r_candidate.remove(each)
break
returnr_candidate
'''''
通過頻繁n-1項集產生候選n項集,並通過先驗定理對候選n項集進行剪枝
方法思路:
1、如果是頻繁1項集,則通過笛卡爾積產生頻繁2項集
2、如果不是頻繁一項集,採用F(k-1)*F(k-1)方法通過頻繁n-1項集產生候選n項集
註:F(k-1)*F(k-1)方法在我的另一篇關聯演算法博客上做了理論上的簡單介紹,或者也可以直接參看《數據挖掘導論》
'''
defget_candidata(frequence,num):
length=len(frequence)
candidate=[]
ifnum==1:
foreachinitertools.combinations(frequence,2):
tmp=list(each)
tmp3=[]
tmp3.append(tmp[0])
tmp3.append(tmp[1])
candidate.append(tmp3)
else:
foriinrange(0,length-1):
tmp1=.deep(frequence[i])
tmp1.pop(num-1)
forjinrange(i+1,length):
tmp2=.deep(frequence[j])
tmp2.pop(num-1)
iftmp1==tmp2:
tmp3=.deep(frequence[i])
tmp3.append(frequence[j][num-1])
candidate.append(tmp3)
candidate2=pre_test(candidate,num,frequence)
returncandidate2
'''''
main程序
'''
if__name__=='__main__':
dataset=getDataSet('dataset.txt')
Item=find_item(dataset)
num=0
frequenceItem=[]
'''''
通過事務集找到頻繁項集,直至頻繁n項集為空,則退出循環
'''
while1:
ifnum==0:
candidate=Item
else:
candidate=get_candidata(frequenceItem[num-1],num)
frequenceItem.append(find_frequent(candidate,dataset,num))
iffrequenceItem[num]==[]:
frequenceItem.pop(num)
break
num=num+1
'''''
列印出頻繁項集
'''
foreachinfrequenceItem:
printeach
目錄位置:
⑷ python dict用法
dic= {key1 : value1, key2 : value2 }
字典也被稱作關聯數組或哈希表。下面是幾種常見的字典屬性:
1、dict.clear()
clear() 用於清空字典中所有元素(鍵-值對),對一個字典執行 clear() 方法之後,該字典就會變成一個空字典。
2、dict.()
() 用於返回一個字典的淺拷貝。
3、dict.fromkeys()
fromkeys() 使用給定的多個鍵創建一個新字典,值默認都是 None,也可以傳入一個參數作為默認的值。
4、dict.get()
get() 用於返回指定鍵的值,也就是根據鍵來獲取值,在鍵不存在的情況下,返回 None,也可以指定返回值。
5、dict.items()
items() 獲取字典中的所有鍵-值對,一般情況下可以將結果轉化為列表再進行後續處理。
6、dict.keys()
keys() 返回一個字典所有的鍵。
⑸ python中""和'的區別
沒什麼區別,成對使用即可,都是字元串的界限符。
單引號表示的字元串里可包含雙引號,但內部不能包含單引號。 雙引號表示的字元串里可以包含單引號,但內部不能包含雙引號。