system: [SYSTEM]

user: 3. 改进的Apriori算法 3.1. 改进算法的思想 改进该算法的主要思想是通过布尔矩阵进行行列压缩，减少事务数据库的扫描次数 [ 6 ] - [ 12 ]；在扫描过程中以索引表的形式替代候选项集，免去了生成大量候选项集的麻烦；在查找频繁项集并计算置信度时以Tried树的形式加快查找速度。 1) 将事务数据库D转换为矩阵Mat，其中事务按照列顺序排序，项集按照行顺序排序，该矩阵的表示如下： T 1     T 2     ⋯   T n Mat = [ d 11 d 12 ⋯ d 1 n d 21 d 22 ⋯ d 2 n ⋮ ⋮ ⋱ ⋮ d m 1 d m 2 ⋯ d m n ] I 1 I 2 ⋮ I m (1) 2) 如果第i个项集在第j个事务中，则矩阵第i行，第j列的值d ij 为1，否则为0，由此得到布尔矩阵。 3) 由上一步得到的布尔矩阵可以计算该矩阵中某一行形成的项集的支持度。支持度由各行向量通过按位与运算得到。 support_count ( \mathrm { C k } ) = ∑ j = 1 n ( d i 1 j ∧ d i 2 j ∧ d i 3 j ∧ ⋯ ∧ d i k j ) (2) 4) 由布尔矩阵以及支持度的计算方法，得到各项集的支持度，依此得到项集索引表，再与所设置的最小支持度比较得到频繁项集。 5) 依据频繁项集的一性质一推论，如果一个项集是非频繁的，那么所有包含该项集的项集也是非频繁的，可以将其直接进行删除，也就是进行行压缩。 6) 由于布尔矩阵每个事务对应一个列向量，所以如果一个事务的长度小于K，那么不可能包含K-频繁项集L k ，在搜索时可直接将该事务删除，也就是进行列压缩。 7) 将压缩后的布尔矩阵再次进行扫描，计算支持度，创建索引表。重复上述步骤，直到不能再产生K-频繁项集，最终以索引表的形式得到所有频繁项集。 8) 最后引用Tried树的形式对所有的频繁项集进行查找，计算置信度，从而产生强关联规则，即产生用户感兴趣的关联规则。 3.2. 改进算法实例说明 以一实例来对该算法进行简单说明，如表1为事务数据库D： Table 1 Database TID 项集 T 1 {1， 2， 5} T 2 {2， 4} T 3 {1， 2， 3， 4} T 4 {1， 2， 4} T 5 {2， 3} T 6 {1， 3} 表1. 数据库D 将该数据库转换为布尔矩阵，该矩阵的表示如下： T 1     T 2       T 3     T 4     T 5     T 6 Mat = 1 2 3 4 5 [ 1 0 1 1 0 1 1 1 1 1 1 0 0 0 1 0 1 1 0 1 1 1 0 0 1 0 0 0 0 0 ] (3) 假设该数据库最小支持度阈值(min_support)为2，通过按位与运算得到各行向量的支持度，形成索引表，如表2。因为min_support = 2，所以Count需要大于等于2，即可把不满足要求的直接删除，得到如表3。 Table 2 Indextable-L Item Count {1} 4 {2} 5 {3} 3 {4} 3 {5} 1 表2. 索引表-L 1 Table 3 Frequent itemsets-L Item Count {1} 4 {2} 5 {3} 3 {4} 3 表3. 频繁项集-L 1 论将频繁项集-L 1 转换为矩阵形式，得到M 1 ，该矩阵的表示如下： T 1     T 2     T 3     T 4     T 5     T 6 M 1 = 1 2 3 4 [ 1 0 1 1 0 1 1 1 1 1 1 0 0 0 1 0 1 1 0 1 1 1 0 0 ] (4) 由M 1 得到索引表-L 2 索与频繁项集-L 2 ，如表4，表5。 Table 4 Indextable-L Item Count {1， 2} 3 {1， 3} 2 {1， 4} 2 {2， 3} 2 {2， 4} 3 表4. 索引表-L 2 Table 5 Frequent itemsets-L Item Count {1， 2} 3 {1， 3} 2 {1， 4} 2 {2， 3} 2 表5. 频繁项集-L 2 再由M 1 删除少于3项的事务，即进行列压缩，得到M 2 ，该矩阵的表示如下： T 3     T 4 M 2 = 1 2 3 4 [ 1 1 1 1 1 0 1 1 ] (5) 由M 2 得到索引表-L 3 索与频繁项集-L 3 ，如表6，表7。 Table 6 Indextable-L Item Count {1， 2， 3} 1 {1， 2， 4} 2 {1， 3， 4} 1 {2， 3， 4} 1 表6. 索引表-L 3 Table 7 Frequent itemsets-L Item Count {1， 2， 4} 2 表7. 频繁项集-L 3 将所得所有频繁项集存入索引表中，然后将频繁项集转换为Tried树的形式进行查找，并计算得到所有满足最小置信度的规则，产生的规则既为强关联规则。 3.3. 改进算法的实现 1) 将数据集转换为矩阵 public void addData(String[ ] projects) { BitSet bitSet = new BitSet(); for (String temp : projects) { ProjectAttr projectAttr = projectMap.get(temp); if (Objects.isNull(projectAttr)) { projectAttr = new ProjectAttr(); projectAttr.index = projectMap.size(); projectMap.put(temp， projectAttr); this.maxProjectSize = projectMap.size(); projectIndexMap.put(projectAttr.index， temp); } projectAttr.count++; bitSet.set(projectAttr.index); }} 1) 行压缩 public Map supportCountOneProjectAndCompressProjects(int threshold) { Map map = new HashMap<>(); List willRemoveProjects = new LinkedList<>(); for (Entry entry : projectMap.entrySet()){ if (entry.getValue().count >= threshold) { map.put(entry.getKey()， entry.getValue().count); } else { willRemoveProjects.add(entry.getKey()); } } 2) 列压缩 public void compressAffair(int threshold) { Iterator iterator = matrix.iterator(); while (iterator.hasNext()) { BitSet next = iterator.next(); if (next.cardinality() < threshold) { iterator.remove(); for (int i = 0; i < next.size(); i++) { if (next.get(i)) { String projectKey = projectIndexMap.get(i); ProjectAttr projectAttr = this.projectMap.get(projectKey); if (Objects.nonNull(projectAttr)) { projectAttr.count--; } } } } }} 3) 索引表查找与Tried树查找 public class IndexRecord implements Comparable { public static IndexRecord of(Collection item， int count) { return new IndexRecord(item， count);} public IndexRecord inspectTakeIndexRecord(final Collection item) { if (Objects.isNull(rootMatcher)) { this.resetMatcher();} TriedNode parent = this.rootMatcher; for (String temp : item) { parent = parent.map.get(temp);} return parent.item;}} private int getCount(Collection collection) { long start = System.nanoTime(); int count = 0; if (triedFlag) { IndexRecordinspectTakeIndexRecord = triedHallows.inspectTakeIndexRecord(collection); if (Objects.nonNull(inspectTakeIndexRecord)) { count = inspectTakeIndexRecord.getCount();} } else { for (IndexRecord indexRecord : indexTable) { if (indexRecord.collectionEquals(collection)) { count = indexRecord.getCount(); break;}}} long end = System.nanoTime(); sum += end - start; return count;}