日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

java gsp_GSP序列模式分析算法

發布時間:2024/8/1 编程问答 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java gsp_GSP序列模式分析算法 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

介紹

GSP算法是序列模式挖掘算法的一種,他是一種類Apriori的一種,整個過程與Apriori算法比較類似,不過在細節上會略有不同,在下面的描述中,將會有所描述。GSP在原有的頻繁模式定義的概念下,增加了3個的概念。

1、加入時間約束min_gap,max_gap,要求原來的連續變為只要滿足在規定的min_gap到max_gap之間即可。

2、加入time_windows_size,只要在windows_size內的item,都可以被認為是同一ItemSet。

3、加入分類標準。

以上3點新的中的第一條特征將會在后面的算法中著重展現。

算法原理

1、根據所輸入的序列,找出所有的單項集,即1頻繁模式,這里會經過最小支持度閾值的判斷。

2、根據1頻繁模式進行連接運算,產生2頻繁模式,這里會有進行最小閾值的判斷。

3、根據2頻繁模式連接產生3頻繁模式,會經過最小支持度判斷和剪枝操作,剪枝操作的原理在于判斷他的所有子集是否也全是頻繁模式。

4、3頻繁模式不斷的挖掘知道不能夠產生出候選集為止。

連接操作的原理

2個序列,全部變為item列表的形式,如果a序列去掉第1個元素后,b序列去掉最后1個序列,2個序列的item完全一致,則代表可以連接,由b的最后一個元素加入到a中,至于是以獨立項集的身份加入還是加入到a中最后1個項集中取決于b中的最后一個元素所屬項集是否為單項項集。

時間約束計算

這個是用在支持度計數使用的,GSP算法的支持度計算不是那么簡單,比如序列判斷<2, <3, 4>>是否在序列, 2>,這就不能僅僅判斷序列中是否只包含2,<3, 4>就行了,還要滿足時間間隔約束,這就要把2,和<3,4>的所有出現時間都找出來,然后再里面找出一條滿足時間約束的路徑就算包含。時間的定義是從左往右起1.2,3...繼續,以1個項集為單位,所有2的時間有2個分別為t=2和t=4,然后同理,因為<3,4>在序列中只有1次,所以時間為t=3,所以問題就變為了下面一個數組的問題

2 ?4

3

從時間數組的上往下,通過對多個時間的組合,找出1條滿足時間約束的方案,這里的方案只有2-3,4-3,然后判斷時間間隔,如果存在這樣的方式,則代表此序列支持所給定序列,支持度值加1,這個算法在程序的實現中是比較復雜的。

算法的代碼實現

測試數據輸入(格式:事務ID item數 item1 item2.....):

1 2 1 5

1 1 2

1 1 3

1 1 4

2 1 1

2 1 3

2 1 4

2 2 3 5

3 1 1

3 1 2

3 1 3

3 1 4

3 1 5

4 1 1

4 1 3

4 1 5

5 1 4

5 1 5最后組成的序列為:

<1 3 4 (3,5)>

<1 2 3 4 5>

<1 3 5>

<4 5>

也就是說同一序列都是同事務的。下面是關鍵的類

Sequence.java:

package DataMining_GSP;

import java.util.ArrayList;

/**

* 序列,每個序列內部包含多組ItemSet項集

*

* @author lyq

*

*/

public class Sequence implements Comparable, Cloneable {

// 序列所屬事務ID

private int trsanctionID;

// 項集列表

private ArrayList itemSetList;

public Sequence(int trsanctionID) {

this.trsanctionID = trsanctionID;

this.itemSetList = new ArrayList<>();

}

public Sequence() {

this.itemSetList = new ArrayList<>();

}

public int getTrsanctionID() {

return trsanctionID;

}

public void setTrsanctionID(int trsanctionID) {

this.trsanctionID = trsanctionID;

}

public ArrayList getItemSetList() {

return itemSetList;

}

public void setItemSetList(ArrayList itemSetList) {

this.itemSetList = itemSetList;

}

/**

* 取出序列中第一個項集的第一個元素

*

* @return

*/

public Integer getFirstItemSetNum() {

return this.getItemSetList().get(0).getItems().get(0);

}

/**

* 獲取序列中最后一個項集

*

* @return

*/

public ItemSet getLastItemSet() {

return getItemSetList().get(getItemSetList().size() - 1);

}

/**

* 獲取序列中最后一個項集的最后一個一個元素

*

* @return

*/

public Integer getLastItemSetNum() {

ItemSet lastItemSet = getItemSetList().get(getItemSetList().size() - 1);

int lastItemNum = lastItemSet.getItems().get(

lastItemSet.getItems().size() - 1);

return lastItemNum;

}

/**

* 判斷序列中最后一個項集是否為單一的值

*

* @return

*/

public boolean isLastItemSetSingleNum() {

ItemSet lastItemSet = getItemSetList().get(getItemSetList().size() - 1);

int size = lastItemSet.getItems().size();

return size == 1 ? true : false;

}

@Override

public int compareTo(Sequence o) {

// TODO Auto-generated method stub

return this.getFirstItemSetNum().compareTo(o.getFirstItemSetNum());

}

@Override

protected Object clone() throws CloneNotSupportedException {

// TODO Auto-generated method stub

return super.clone();

}

/**

* 拷貝一份一模一樣的序列

*/

public Sequence copySeqence(){

Sequence copySeq = new Sequence();

for(ItemSet itemSet: this.itemSetList){

copySeq.getItemSetList().add(new ItemSet(itemSet.copyItems()));

}

return copySeq;

}

/**

* 比較2個序列是否相等,需要判斷內部的每個項集是否完全一致

*

* @param seq

* 比較的序列對象

* @return

*/

public boolean compareIsSame(Sequence seq) {

boolean result = true;

ArrayList itemSetList2 = seq.getItemSetList();

ItemSet tempItemSet1;

ItemSet tempItemSet2;

if (itemSetList2.size() != this.itemSetList.size()) {

return false;

}

for (int i = 0; i < itemSetList2.size(); i++) {

tempItemSet1 = this.itemSetList.get(i);

tempItemSet2 = itemSetList2.get(i);

if (!tempItemSet1.compareIsSame(tempItemSet2)) {

// 只要不相等,直接退出函數

result = false;

break;

}

}

return result;

}

/**

* 生成此序列的所有子序列

*

* @return

*/

public ArrayList createChildSeqs() {

ArrayList childSeqs = new ArrayList<>();

ArrayList tempItems;

Sequence tempSeq = null;

ItemSet tempItemSet;

for (int i = 0; i < this.itemSetList.size(); i++) {

tempItemSet = itemSetList.get(i);

if (tempItemSet.getItems().size() == 1) {

tempSeq = this.copySeqence();

// 如果只有項集中只有1個元素,則直接移除

tempSeq.itemSetList.remove(i);

childSeqs.add(tempSeq);

} else {

tempItems = tempItemSet.getItems();

for (int j = 0; j < tempItems.size(); j++) {

tempSeq = this.copySeqence();

// 在拷貝的序列中移除一個數字

tempSeq.getItemSetList().get(i).getItems().remove(j);

childSeqs.add(tempSeq);

}

}

}

return childSeqs;

}

}ItemSet.java:

package DataMining_GSP;

import java.util.ArrayList;

/**

* 序列中的子項集

*

* @author lyq

*

*/

public class ItemSet {

/**

* 項集中保存的是數字項數組

*/

private ArrayList items;

public ItemSet(String[] itemStr) {

items = new ArrayList<>();

for (String s : itemStr) {

items.add(Integer.parseInt(s));

}

}

public ItemSet(int[] itemNum) {

items = new ArrayList<>();

for (int num : itemNum) {

items.add(num);

}

}

public ItemSet(ArrayList itemNum) {

this.items = itemNum;

}

public ArrayList getItems() {

return items;

}

public void setItems(ArrayList items) {

this.items = items;

}

/**

* 判斷2個項集是否相等

*

* @param itemSet

* 比較對象

* @return

*/

public boolean compareIsSame(ItemSet itemSet) {

boolean result = true;

if (this.items.size() != itemSet.items.size()) {

return false;

}

for (int i = 0; i < itemSet.items.size(); i++) {

if (this.items.get(i) != itemSet.items.get(i)) {

// 只要有值不相等,直接算作不相等

result = false;

break;

}

}

return result;

}

/**

* 拷貝項集中同樣的數據一份

*

* @return

*/

public ArrayList copyItems() {

ArrayList copyItems = new ArrayList<>();

for (int num : this.items) {

copyItems.add(num);

}

return copyItems;

}

}GSPTool.java(算法工具類):

package DataMining_GSP;

import java.io.BufferedReader;

import java.io.File;

import java.io.FileReader;

import java.io.IOException;

import java.util.ArrayList;

import java.util.Collections;

import java.util.HashMap;

import java.util.Map;

/**

* GSP序列模式分析算法

*

* @author lyq

*

*/

public class GSPTool {

// 測試數據文件地址

private String filePath;

// 最小支持度閾值

private int minSupportCount;

// 時間最小間隔

private int min_gap;

// 時間最大間隔

private int max_gap;

// 原始數據序列

private ArrayList totalSequences;

// GSP算法中產生的所有的頻繁項集序列

private ArrayList totalFrequencySeqs;

// 序列項數字對時間的映射圖容器

private ArrayList>> itemNum2Time;

public GSPTool(String filePath, int minSupportCount, int min_gap,

int max_gap) {

this.filePath = filePath;

this.minSupportCount = minSupportCount;

this.min_gap = min_gap;

this.max_gap = max_gap;

totalFrequencySeqs = new ArrayList<>();

readDataFile();

}

/**

* 從文件中讀取數據

*/

private void readDataFile() {

File file = new File(filePath);

ArrayList dataArray = new ArrayList();

try {

BufferedReader in = new BufferedReader(new FileReader(file));

String str;

String[] tempArray;

while ((str = in.readLine()) != null) {

tempArray = str.split(" ");

dataArray.add(tempArray);

}

in.close();

} catch (IOException e) {

e.getStackTrace();

}

HashMap mapSeq = new HashMap<>();

Sequence seq;

ItemSet itemSet;

int tID;

String[] itemStr;

for (String[] str : dataArray) {

tID = Integer.parseInt(str[0]);

itemStr = new String[Integer.parseInt(str[1])];

System.arraycopy(str, 2, itemStr, 0, itemStr.length);

itemSet = new ItemSet(itemStr);

if (mapSeq.containsKey(tID)) {

seq = mapSeq.get(tID);

} else {

seq = new Sequence(tID);

}

seq.getItemSetList().add(itemSet);

mapSeq.put(tID, seq);

}

// 將序列圖加入到序列List中

totalSequences = new ArrayList<>();

for (Map.Entry entry : mapSeq.entrySet()) {

totalSequences.add((Sequence) entry.getValue());

}

}

/**

* 生成1頻繁項集

*

* @return

*/

private ArrayList generateOneFrequencyItem() {

int count = 0;

int currentTransanctionID = 0;

Sequence tempSeq;

ItemSet tempItemSet;

HashMap itemNumMap = new HashMap<>();

ArrayList seqList = new ArrayList<>();

for (Sequence seq : totalSequences) {

for (ItemSet itemSet : seq.getItemSetList()) {

for (int num : itemSet.getItems()) {

// 如果沒有此種類型項,則進行添加操作

if (!itemNumMap.containsKey(num)) {

itemNumMap.put(num, 1);

}

}

}

}

boolean isContain = false;

int number = 0;

for (Map.Entry entry : itemNumMap.entrySet()) {

count = 0;

number = (int) entry.getKey();

for (Sequence seq : totalSequences) {

isContain = false;

for (ItemSet itemSet : seq.getItemSetList()) {

for (int num : itemSet.getItems()) {

if (num == number) {

isContain = true;

break;

}

}

if(isContain){

break;

}

}

if(isContain){

count++;

}

}

itemNumMap.put(number, count);

}

for (Map.Entry entry : itemNumMap.entrySet()) {

count = (int) entry.getValue();

if (count >= minSupportCount) {

tempSeq = new Sequence();

tempItemSet = new ItemSet(new int[] { (int) entry.getKey() });

tempSeq.getItemSetList().add(tempItemSet);

seqList.add(tempSeq);

}

}

// 將序列升序排列

Collections.sort(seqList);

// 將頻繁1項集加入總頻繁項集列表中

totalFrequencySeqs.addAll(seqList);

return seqList;

}

/**

* 通過1頻繁項集連接產生2頻繁項集

*

* @param oneSeq

* 1頻繁項集序列

* @return

*/

private ArrayList generateTwoFrequencyItem(

ArrayList oneSeq) {

Sequence tempSeq;

ArrayList resultSeq = new ArrayList<>();

ItemSet tempItemSet;

int num1;

int num2;

// 假如將,2個1頻繁項集做連接組合,可以分為

// 注意此時的每個序列中包含2個獨立項集

for (int i = 0; i < oneSeq.size(); i++) {

num1 = oneSeq.get(i).getFirstItemSetNum();

for (int j = 0; j < oneSeq.size(); j++) {

num2 = oneSeq.get(j).getFirstItemSetNum();

tempSeq = new Sequence();

tempItemSet = new ItemSet(new int[] { num1 });

tempSeq.getItemSetList().add(tempItemSet);

tempItemSet = new ItemSet(new int[] { num2 });

tempSeq.getItemSetList().add(tempItemSet);

if (countSupport(tempSeq) >= minSupportCount) {

resultSeq.add(tempSeq);

}

}

}

// 上面連接還有1種情況是每個序列中只包含有一個項集的情況,此時a,b的劃分則是

for (int i = 0; i < oneSeq.size(); i++) {

num1 = oneSeq.get(i).getFirstItemSetNum();

for (int j = i; j < oneSeq.size(); j++) {

num2 = oneSeq.get(j).getFirstItemSetNum();

tempSeq = new Sequence();

tempItemSet = new ItemSet(new int[] { num1, num2 });

tempSeq.getItemSetList().add(tempItemSet);

if (countSupport(tempSeq) >= minSupportCount) {

resultSeq.add(tempSeq);

}

}

}

// 同樣將2頻繁項集加入到總頻繁項集中

totalFrequencySeqs.addAll(resultSeq);

return resultSeq;

}

/**

* 根據上次的頻繁集連接產生新的侯選集

*

* @param seqList

* 上次產生的候選集

* @return

*/

private ArrayList generateCandidateItem(

ArrayList seqList) {

Sequence tempSeq;

ArrayList tempNumArray;

ArrayList resultSeq = new ArrayList<>();

// 序列數字項列表

ArrayList> seqNums = new ArrayList<>();

for (int i = 0; i < seqList.size(); i++) {

tempNumArray = new ArrayList<>();

tempSeq = seqList.get(i);

for (ItemSet itemSet : tempSeq.getItemSetList()) {

tempNumArray.addAll(itemSet.copyItems());

}

seqNums.add(tempNumArray);

}

ArrayList array1;

ArrayList array2;

// 序列i,j的拷貝

Sequence seqi = null;

Sequence seqj = null;

// 判斷是否能夠連接,默認能連接

boolean canConnect = true;

// 進行連接運算,包括自己與自己連接

for (int i = 0; i < seqNums.size(); i++) {

for (int j = 0; j < seqNums.size(); j++) {

array1 = (ArrayList) seqNums.get(i).clone();

array2 = (ArrayList) seqNums.get(j).clone();

// 將第一個數字組去掉第一個,第二個數字組去掉最后一個,如果剩下的部分相等,則可以連接

array1.remove(0);

array2.remove(array2.size() - 1);

canConnect = true;

for (int k = 0; k < array1.size(); k++) {

if (array1.get(k) != array2.get(k)) {

canConnect = false;

break;

}

}

if (canConnect) {

seqi = seqList.get(i).copySeqence();

seqj = seqList.get(j).copySeqence();

int lastItemNum = seqj.getLastItemSetNum();

if (seqj.isLastItemSetSingleNum()) {

// 如果j序列的最后項集為單一值,則最后一個數字以獨立項集加入i序列

ItemSet itemSet = new ItemSet(new int[] { lastItemNum });

seqi.getItemSetList().add(itemSet);

} else {

// 如果j序列的最后項集為非單一值,則最后一個數字加入i序列最后一個項集中

ItemSet itemSet = seqi.getLastItemSet();

itemSet.getItems().add(lastItemNum);

}

// 判斷是否超過最小支持度閾值

if (isChildSeqContained(seqi)

&& countSupport(seqi) >= minSupportCount) {

resultSeq.add(seqi);

}

}

}

}

totalFrequencySeqs.addAll(resultSeq);

return resultSeq;

}

/**

* 判斷此序列的所有子序列是否也是頻繁序列

*

* @param seq

* 待比較序列

* @return

*/

private boolean isChildSeqContained(Sequence seq) {

boolean isContained = false;

ArrayList childSeqs;

childSeqs = seq.createChildSeqs();

for (Sequence tempSeq : childSeqs) {

isContained = false;

for (Sequence frequencySeq : totalFrequencySeqs) {

if (tempSeq.compareIsSame(frequencySeq)) {

isContained = true;

break;

}

}

if (!isContained) {

break;

}

}

return isContained;

}

/**

* 候選集判斷支持度的值

*

* @param seq

* 待判斷序列

* @return

*/

private int countSupport(Sequence seq) {

int count = 0;

int matchNum = 0;

Sequence tempSeq;

ItemSet tempItemSet;

HashMap timeMap;

ArrayList itemSetList;

ArrayList> numArray = new ArrayList<>();

// 每項集對應的時間鏈表

ArrayList> timeArray = new ArrayList<>();

for (ItemSet itemSet : seq.getItemSetList()) {

numArray.add(itemSet.getItems());

}

for (int i = 0; i < totalSequences.size(); i++) {

timeArray = new ArrayList<>();

for (int s = 0; s < numArray.size(); s++) {

ArrayList childNum = numArray.get(s);

ArrayList localTime = new ArrayList<>();

tempSeq = totalSequences.get(i);

itemSetList = tempSeq.getItemSetList();

for (int j = 0; j < itemSetList.size(); j++) {

tempItemSet = itemSetList.get(j);

matchNum = 0;

int t = 0;

if (tempItemSet.getItems().size() == childNum.size()) {

timeMap = itemNum2Time.get(i).get(j);

// 只有當項集長度匹配時才匹配

for (int k = 0; k < childNum.size(); k++) {

if (timeMap.containsKey(childNum.get(k))) {

matchNum++;

t = timeMap.get(childNum.get(k));

}

}

// 如果完全匹配,則記錄時間

if (matchNum == childNum.size()) {

localTime.add(t);

}

}

}

if (localTime.size() > 0) {

timeArray.add(localTime);

}

}

// 判斷時間是否滿足時間最大最小約束,如果滿足,則此條事務包含候選事務

if (timeArray.size() == numArray.size()

&& judgeTimeInGap(timeArray)) {

count++;

}

}

return count;

}

/**

* 判斷事務是否滿足時間約束

*

* @param timeArray

* 時間數組,每行代表各項集的在事務中的發生時間鏈表

* @return

*/

private boolean judgeTimeInGap(ArrayList> timeArray) {

boolean result = false;

int preTime = 0;

ArrayList firstTimes = timeArray.get(0);

timeArray.remove(0);

if (timeArray.size() == 0) {

return false;

}

for (int i = 0; i < firstTimes.size(); i++) {

preTime = firstTimes.get(i);

if (dfsJudgeTime(preTime, timeArray)) {

result = true;

break;

}

}

return result;

}

/**

* 深度優先遍歷時間,判斷是否有符合條件的時間間隔

*

* @param preTime

* @param timeArray

* @return

*/

private boolean dfsJudgeTime(int preTime,

ArrayList> timeArray) {

boolean result = false;

ArrayList> timeArrayClone = (ArrayList>) timeArray

.clone();

ArrayList firstItemItem = timeArrayClone.get(0);

for (int i = 0; i < firstItemItem.size(); i++) {

if (firstItemItem.get(i) - preTime >= min_gap

&& firstItemItem.get(i) - preTime <= max_gap) {

// 如果此2項間隔時間滿足時間約束,則繼續往下遞歸

preTime = firstItemItem.get(i);

timeArrayClone.remove(0);

if (timeArrayClone.size() == 0) {

return true;

} else {

result = dfsJudgeTime(preTime, timeArrayClone);

if (result) {

return true;

}

}

}

}

return result;

}

/**

* 初始化序列項到時間的序列圖,為了后面的時間約束計算

*/

private void initItemNumToTimeMap() {

Sequence seq;

itemNum2Time = new ArrayList<>();

HashMap tempMap;

ArrayList> tempMapList;

for (int i = 0; i < totalSequences.size(); i++) {

seq = totalSequences.get(i);

tempMapList = new ArrayList<>();

for (int j = 0; j < seq.getItemSetList().size(); j++) {

ItemSet itemSet = seq.getItemSetList().get(j);

tempMap = new HashMap<>();

for (int itemNum : itemSet.getItems()) {

tempMap.put(itemNum, j + 1);

}

tempMapList.add(tempMap);

}

itemNum2Time.add(tempMapList);

}

}

/**

* 進行GSP算法計算

*/

public void gspCalculate() {

ArrayList oneSeq;

ArrayList twoSeq;

ArrayList candidateSeq;

initItemNumToTimeMap();

oneSeq = generateOneFrequencyItem();

twoSeq = generateTwoFrequencyItem(oneSeq);

candidateSeq = twoSeq;

// 不斷連接生產候選集,直到沒有產生出侯選集

for (;;) {

candidateSeq = generateCandidateItem(candidateSeq);

if (candidateSeq.size() == 0) {

break;

}

}

outputSeqence(totalFrequencySeqs);

}

/**

* 輸出序列列表信息

*

* @param outputSeqList

* 待輸出序列列表

*/

private void outputSeqence(ArrayList outputSeqList) {

for (Sequence seq : outputSeqList) {

System.out.print("

for (ItemSet itemSet : seq.getItemSetList()) {

System.out.print("(");

for (int num : itemSet.getItems()) {

System.out.print(num + ",");

}

System.out.print("), ");

}

System.out.println(">");

}

}

}調用類Client.java:

package DataMining_GSP;

/**

* GSP序列模式分析算法

* @author lyq

*

*/

public class Client {

public static void main(String[] args){

String filePath = "C:\\Users\\lyq\\Desktop\\icon\\testInput.txt";

//最小支持度閾值

int minSupportCount = 2;

//時間最小間隔

int min_gap = 1;

//施加最大間隔

int max_gap = 5;

GSPTool tool = new GSPTool(filePath, minSupportCount, min_gap, max_gap);

tool.gspCalculate();

}

}算法的輸出(挖掘出的所有頻繁模式):

算法實現的難點

1、算法花費了幾天的時間,難點首先在于對算法原理本身的理解,網上對于此算法的資料特別少,而且不同的人所表達的意思 都有少許的不同,講的也不是很詳細,于是就通過閱讀別人的代碼理解GSP算法的原理,我的代碼實現也是參考了參考資料的C語言的實現。

2、在實現時間約束的支持度計數統計的時候,調試了一段時間,做時間統計容易出錯,因為層級實在太多容易搞暈。

3、還有1個是Sequence和ItemSet的拷貝時的引用問題,在產生新的序列時一定要深拷貝1個否則導致同一引用會把原數據給改掉的。

GSP算法和Apriori算法的比較

我是都實現過了GSP算法和Apriori算法的,后者是被稱為關聯規則挖掘算法,偏向于挖掘關聯規則的,2個算法在連接的操作上有不一樣的地方,還有在數據的構成方式上,Apriori的數據會簡單一點,都是單項單項構成的,而且在做支持度統計的時候只需判斷存在與否即可。不需要考慮時間約束。Apriori算法給定K項集,連接到K-1項集算法就停止了,而GSP算法是直到不能夠產生候選集為止。

總結

以上是生活随笔為你收集整理的java gsp_GSP序列模式分析算法的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。