java gsp_GSP序列模式分析算法
介紹
GSP算法是序列模式挖掘算法的一種,他是一種類(lèi)Apriori的一種,整個(gè)過(guò)程與Apriori算法比較類(lèi)似,不過(guò)在細(xì)節(jié)上會(huì)略有不同,在下面的描述中,將會(huì)有所描述。GSP在原有的頻繁模式定義的概念下,增加了3個(gè)的概念。
1、加入時(shí)間約束min_gap,max_gap,要求原來(lái)的連續(xù)變?yōu)橹灰獫M足在規(guī)定的min_gap到max_gap之間即可。
2、加入time_windows_size,只要在windows_size內(nèi)的item,都可以被認(rèn)為是同一ItemSet。
3、加入分類(lèi)標(biāo)準(zhǔn)。
以上3點(diǎn)新的中的第一條特征將會(huì)在后面的算法中著重展現(xiàn)。
算法原理
1、根據(jù)所輸入的序列,找出所有的單項(xiàng)集,即1頻繁模式,這里會(huì)經(jīng)過(guò)最小支持度閾值的判斷。
2、根據(jù)1頻繁模式進(jìn)行連接運(yùn)算,產(chǎn)生2頻繁模式,這里會(huì)有進(jìn)行最小閾值的判斷。
3、根據(jù)2頻繁模式連接產(chǎn)生3頻繁模式,會(huì)經(jīng)過(guò)最小支持度判斷和剪枝操作,剪枝操作的原理在于判斷他的所有子集是否也全是頻繁模式。
4、3頻繁模式不斷的挖掘知道不能夠產(chǎn)生出候選集為止。
連接操作的原理
2個(gè)序列,全部變?yōu)閕tem列表的形式,如果a序列去掉第1個(gè)元素后,b序列去掉最后1個(gè)序列,2個(gè)序列的item完全一致,則代表可以連接,由b的最后一個(gè)元素加入到a中,至于是以獨(dú)立項(xiàng)集的身份加入還是加入到a中最后1個(gè)項(xiàng)集中取決于b中的最后一個(gè)元素所屬項(xiàng)集是否為單項(xiàng)項(xiàng)集。
時(shí)間約束計(jì)算
這個(gè)是用在支持度計(jì)數(shù)使用的,GSP算法的支持度計(jì)算不是那么簡(jiǎn)單,比如序列判斷<2, <3, 4>>是否在序列, 2>,這就不能僅僅判斷序列中是否只包含2,<3, 4>就行了,還要滿足時(shí)間間隔約束,這就要把2,和<3,4>的所有出現(xiàn)時(shí)間都找出來(lái),然后再里面找出一條滿足時(shí)間約束的路徑就算包含。時(shí)間的定義是從左往右起1.2,3...繼續(xù),以1個(gè)項(xiàng)集為單位,所有2的時(shí)間有2個(gè)分別為t=2和t=4,然后同理,因?yàn)?lt;3,4>在序列中只有1次,所以時(shí)間為t=3,所以問(wèn)題就變?yōu)榱讼旅嬉粋€(gè)數(shù)組的問(wèn)題
2 ?4
3
從時(shí)間數(shù)組的上往下,通過(guò)對(duì)多個(gè)時(shí)間的組合,找出1條滿足時(shí)間約束的方案,這里的方案只有2-3,4-3,然后判斷時(shí)間間隔,如果存在這樣的方式,則代表此序列支持所給定序列,支持度值加1,這個(gè)算法在程序的實(shí)現(xiàn)中是比較復(fù)雜的。
算法的代碼實(shí)現(xiàn)
測(cè)試數(shù)據(jù)輸入(格式:事務(wù)ID item數(shù) 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>
也就是說(shuō)同一序列都是同事務(wù)的。下面是關(guān)鍵的類(lèi)
Sequence.java:
package DataMining_GSP;
import java.util.ArrayList;
/**
* 序列,每個(gè)序列內(nèi)部包含多組ItemSet項(xiàng)集
*
* @author lyq
*
*/
public class Sequence implements Comparable, Cloneable {
// 序列所屬事務(wù)ID
private int trsanctionID;
// 項(xiàng)集列表
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;
}
/**
* 取出序列中第一個(gè)項(xiàng)集的第一個(gè)元素
*
* @return
*/
public Integer getFirstItemSetNum() {
return this.getItemSetList().get(0).getItems().get(0);
}
/**
* 獲取序列中最后一個(gè)項(xiàng)集
*
* @return
*/
public ItemSet getLastItemSet() {
return getItemSetList().get(getItemSetList().size() - 1);
}
/**
* 獲取序列中最后一個(gè)項(xiàng)集的最后一個(gè)一個(gè)元素
*
* @return
*/
public Integer getLastItemSetNum() {
ItemSet lastItemSet = getItemSetList().get(getItemSetList().size() - 1);
int lastItemNum = lastItemSet.getItems().get(
lastItemSet.getItems().size() - 1);
return lastItemNum;
}
/**
* 判斷序列中最后一個(gè)項(xiàng)集是否為單一的值
*
* @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個(gè)序列是否相等,需要判斷內(nèi)部的每個(gè)項(xiàng)集是否完全一致
*
* @param seq
* 比較的序列對(duì)象
* @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)) {
// 只要不相等,直接退出函數(shù)
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();
// 如果只有項(xiàng)集中只有1個(gè)元素,則直接移除
tempSeq.itemSetList.remove(i);
childSeqs.add(tempSeq);
} else {
tempItems = tempItemSet.getItems();
for (int j = 0; j < tempItems.size(); j++) {
tempSeq = this.copySeqence();
// 在拷貝的序列中移除一個(gè)數(shù)字
tempSeq.getItemSetList().get(i).getItems().remove(j);
childSeqs.add(tempSeq);
}
}
}
return childSeqs;
}
}ItemSet.java:
package DataMining_GSP;
import java.util.ArrayList;
/**
* 序列中的子項(xiàng)集
*
* @author lyq
*
*/
public class ItemSet {
/**
* 項(xiàng)集中保存的是數(shù)字項(xiàng)數(shù)組
*/
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個(gè)項(xiàng)集是否相等
*
* @param itemSet
* 比較對(duì)象
* @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;
}
/**
* 拷貝項(xiàng)集中同樣的數(shù)據(jù)一份
*
* @return
*/
public ArrayList copyItems() {
ArrayList copyItems = new ArrayList<>();
for (int num : this.items) {
copyItems.add(num);
}
return copyItems;
}
}GSPTool.java(算法工具類(lèi)):
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 {
// 測(cè)試數(shù)據(jù)文件地址
private String filePath;
// 最小支持度閾值
private int minSupportCount;
// 時(shí)間最小間隔
private int min_gap;
// 時(shí)間最大間隔
private int max_gap;
// 原始數(shù)據(jù)序列
private ArrayList totalSequences;
// GSP算法中產(chǎn)生的所有的頻繁項(xiàng)集序列
private ArrayList totalFrequencySeqs;
// 序列項(xiàng)數(shù)字對(duì)時(shí)間的映射圖容器
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();
}
/**
* 從文件中讀取數(shù)據(jù)
*/
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頻繁項(xiàng)集
*
* @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()) {
// 如果沒(méi)有此種類(lèi)型項(xiàng),則進(jìn)行添加操作
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項(xiàng)集加入總頻繁項(xiàng)集列表中
totalFrequencySeqs.addAll(seqList);
return seqList;
}
/**
* 通過(guò)1頻繁項(xiàng)集連接產(chǎn)生2頻繁項(xiàng)集
*
* @param oneSeq
* 1頻繁項(xiàng)集序列
* @return
*/
private ArrayList generateTwoFrequencyItem(
ArrayList oneSeq) {
Sequence tempSeq;
ArrayList resultSeq = new ArrayList<>();
ItemSet tempItemSet;
int num1;
int num2;
// 假如將,2個(gè)1頻繁項(xiàng)集做連接組合,可以分為
// 注意此時(shí)的每個(gè)序列中包含2個(gè)獨(dú)立項(xiàng)集
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種情況是每個(gè)序列中只包含有一個(gè)項(xiàng)集的情況,此時(shí)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頻繁項(xiàng)集加入到總頻繁項(xiàng)集中
totalFrequencySeqs.addAll(resultSeq);
return resultSeq;
}
/**
* 根據(jù)上次的頻繁集連接產(chǎn)生新的侯選集
*
* @param seqList
* 上次產(chǎn)生的候選集
* @return
*/
private ArrayList generateCandidateItem(
ArrayList seqList) {
Sequence tempSeq;
ArrayList tempNumArray;
ArrayList resultSeq = new ArrayList<>();
// 序列數(shù)字項(xiàng)列表
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;
// 判斷是否能夠連接,默認(rèn)能連接
boolean canConnect = true;
// 進(jìn)行連接運(yùn)算,包括自己與自己連接
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();
// 將第一個(gè)數(shù)字組去掉第一個(gè),第二個(gè)數(shù)字組去掉最后一個(gè),如果剩下的部分相等,則可以連接
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序列的最后項(xiàng)集為單一值,則最后一個(gè)數(shù)字以獨(dú)立項(xiàng)集加入i序列
ItemSet itemSet = new ItemSet(new int[] { lastItemNum });
seqi.getItemSetList().add(itemSet);
} else {
// 如果j序列的最后項(xiàng)集為非單一值,則最后一個(gè)數(shù)字加入i序列最后一個(gè)項(xiàng)集中
ItemSet itemSet = seqi.getLastItemSet();
itemSet.getItems().add(lastItemNum);
}
// 判斷是否超過(guò)最小支持度閾值
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<>();
// 每項(xiàng)集對(duì)應(yīng)的時(shí)間鏈表
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);
// 只有當(dāng)項(xiàng)集長(zhǎng)度匹配時(shí)才匹配
for (int k = 0; k < childNum.size(); k++) {
if (timeMap.containsKey(childNum.get(k))) {
matchNum++;
t = timeMap.get(childNum.get(k));
}
}
// 如果完全匹配,則記錄時(shí)間
if (matchNum == childNum.size()) {
localTime.add(t);
}
}
}
if (localTime.size() > 0) {
timeArray.add(localTime);
}
}
// 判斷時(shí)間是否滿足時(shí)間最大最小約束,如果滿足,則此條事務(wù)包含候選事務(wù)
if (timeArray.size() == numArray.size()
&& judgeTimeInGap(timeArray)) {
count++;
}
}
return count;
}
/**
* 判斷事務(wù)是否滿足時(shí)間約束
*
* @param timeArray
* 時(shí)間數(shù)組,每行代表各項(xiàng)集的在事務(wù)中的發(fā)生時(shí)間鏈表
* @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;
}
/**
* 深度優(yōu)先遍歷時(shí)間,判斷是否有符合條件的時(shí)間間隔
*
* @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項(xiàng)間隔時(shí)間滿足時(shí)間約束,則繼續(xù)往下遞歸
preTime = firstItemItem.get(i);
timeArrayClone.remove(0);
if (timeArrayClone.size() == 0) {
return true;
} else {
result = dfsJudgeTime(preTime, timeArrayClone);
if (result) {
return true;
}
}
}
}
return result;
}
/**
* 初始化序列項(xiàng)到時(shí)間的序列圖,為了后面的時(shí)間約束計(jì)算
*/
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);
}
}
/**
* 進(jìn)行GSP算法計(jì)算
*/
public void gspCalculate() {
ArrayList oneSeq;
ArrayList twoSeq;
ArrayList candidateSeq;
initItemNumToTimeMap();
oneSeq = generateOneFrequencyItem();
twoSeq = generateTwoFrequencyItem(oneSeq);
candidateSeq = twoSeq;
// 不斷連接生產(chǎn)候選集,直到?jīng)]有產(chǎn)生出侯選集
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(">");
}
}
}調(diào)用類(lèi)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;
//時(shí)間最小間隔
int min_gap = 1;
//施加最大間隔
int max_gap = 5;
GSPTool tool = new GSPTool(filePath, minSupportCount, min_gap, max_gap);
tool.gspCalculate();
}
}算法的輸出(挖掘出的所有頻繁模式):
算法實(shí)現(xiàn)的難點(diǎn)
1、算法花費(fèi)了幾天的時(shí)間,難點(diǎn)首先在于對(duì)算法原理本身的理解,網(wǎng)上對(duì)于此算法的資料特別少,而且不同的人所表達(dá)的意思 都有少許的不同,講的也不是很詳細(xì),于是就通過(guò)閱讀別人的代碼理解GSP算法的原理,我的代碼實(shí)現(xiàn)也是參考了參考資料的C語(yǔ)言的實(shí)現(xiàn)。
2、在實(shí)現(xiàn)時(shí)間約束的支持度計(jì)數(shù)統(tǒng)計(jì)的時(shí)候,調(diào)試了一段時(shí)間,做時(shí)間統(tǒng)計(jì)容易出錯(cuò),因?yàn)閷蛹?jí)實(shí)在太多容易搞暈。
3、還有1個(gè)是Sequence和ItemSet的拷貝時(shí)的引用問(wèn)題,在產(chǎn)生新的序列時(shí)一定要深拷貝1個(gè)否則導(dǎo)致同一引用會(huì)把原數(shù)據(jù)給改掉的。
GSP算法和Apriori算法的比較
我是都實(shí)現(xiàn)過(guò)了GSP算法和Apriori算法的,后者是被稱(chēng)為關(guān)聯(lián)規(guī)則挖掘算法,偏向于挖掘關(guān)聯(lián)規(guī)則的,2個(gè)算法在連接的操作上有不一樣的地方,還有在數(shù)據(jù)的構(gòu)成方式上,Apriori的數(shù)據(jù)會(huì)簡(jiǎn)單一點(diǎn),都是單項(xiàng)單項(xiàng)構(gòu)成的,而且在做支持度統(tǒng)計(jì)的時(shí)候只需判斷存在與否即可。不需要考慮時(shí)間約束。Apriori算法給定K項(xiàng)集,連接到K-1項(xiàng)集算法就停止了,而GSP算法是直到不能夠產(chǎn)生候選集為止。
總結(jié)
以上是生活随笔為你收集整理的java gsp_GSP序列模式分析算法的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: java 判断端口是否被占用_java检
- 下一篇: python 列联表自动拆分_pytho