|
|
|
|
@ -50,6 +50,9 @@
|
|
|
|
|
<div class="left-top" style="margin-top: 50px">
|
|
|
|
|
<span>三、模型参数设置</span>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="metrics-table">
|
|
|
|
|
<el-button @click="codeSetting">代码设置</el-button>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="metrics-table" style="margin-top: 10px">
|
|
|
|
|
<span style="font-weight: 400; font-size: 12px; color: #ffffff">聚类方法:</span>
|
|
|
|
|
<div class="metrics" style="margin-top: 10px">
|
|
|
|
|
@ -322,9 +325,17 @@
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
</pop-model>
|
|
|
|
|
<pop-model :showModel="runResultShow2" title="设置代码" @closePop="closeCode">
|
|
|
|
|
<template v-slot:content>
|
|
|
|
|
<div>
|
|
|
|
|
<codemirror :code="code"></codemirror>
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
</pop-model>
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<script setup>
|
|
|
|
|
import codemirror from "@/components/codemirror/index.vue"
|
|
|
|
|
import useAlgorithmStore from "@/store/modules/algorithm.js";
|
|
|
|
|
const algorithmStore = useAlgorithmStore();
|
|
|
|
|
import * as portraitModel from "@/api/portraitModel";
|
|
|
|
|
@ -344,6 +355,7 @@ const formData = reactive({
|
|
|
|
|
value4: "",
|
|
|
|
|
value5: "",
|
|
|
|
|
});
|
|
|
|
|
const code=ref('')
|
|
|
|
|
const scrollbar=ref(null)
|
|
|
|
|
const loading1 =ref(false)
|
|
|
|
|
const task = () => {
|
|
|
|
|
@ -377,78 +389,22 @@ const task = () => {
|
|
|
|
|
proxy.$modal.msgSuccess("提交成功");
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
const runResultShow2 = ref(false)
|
|
|
|
|
const closeCode=()=>{
|
|
|
|
|
runResultShow2.value = false
|
|
|
|
|
const inputs = document.querySelectorAll('.codemirror pre code input')
|
|
|
|
|
const values = []
|
|
|
|
|
inputs.forEach(input => {
|
|
|
|
|
values.push(input.value)
|
|
|
|
|
})
|
|
|
|
|
input5.value=values[0]*100
|
|
|
|
|
input6.value=values[1]*100
|
|
|
|
|
input4.value='Apriori关联算法'
|
|
|
|
|
}
|
|
|
|
|
const dialogVisible = ref(false);
|
|
|
|
|
const runResultShow = ref(false);
|
|
|
|
|
const tableLabel = reactive([{ prop: "date", label: "" }]);
|
|
|
|
|
const tableLabel2 = reactive([{ prop: "date", label: "" }]);
|
|
|
|
|
const text = ref(`首先导入必要的库:
|
|
|
|
|
\`\`\`python
|
|
|
|
|
from itertools import chain, combinations
|
|
|
|
|
\`\`\`
|
|
|
|
|
接着定义几个辅助函数:
|
|
|
|
|
\`\`\`python
|
|
|
|
|
# 生成候选项集的所有非空子集
|
|
|
|
|
def powerset(s):
|
|
|
|
|
return chain.from_iterable(combinations(s, r) for r in range(1, len(s)))
|
|
|
|
|
# 计算支持度
|
|
|
|
|
def calculate_support(itemset, transactions):
|
|
|
|
|
return sum(1 for transaction in transactions if itemset.issubset(transaction)) / len(transactions)
|
|
|
|
|
\`\`\`
|
|
|
|
|
现在我们来实现Apriori算法:
|
|
|
|
|
\`\`\`python
|
|
|
|
|
def apriori(transactions, min_support, min_confidence):
|
|
|
|
|
# 初始化频繁项集和关联规则列表
|
|
|
|
|
frequent_itemsets = []
|
|
|
|
|
association_rules = []
|
|
|
|
|
# 第一步:找出单项频繁项集
|
|
|
|
|
singletons = {frozenset([item]) for transaction in transactions for item in transaction}
|
|
|
|
|
singletons = {itemset for itemset in singletons if calculate_support(itemset, transactions) >= min_support}
|
|
|
|
|
frequent_itemsets.extend(singletons)
|
|
|
|
|
# 迭代找出所有其他频繁项集
|
|
|
|
|
prev_frequent_itemsets = singletons
|
|
|
|
|
while prev_frequent_itemsets:
|
|
|
|
|
# 生成新的候选项集
|
|
|
|
|
candidates = {itemset1 | itemset2 for itemset1 in prev_frequent_itemsets for itemset2 in prev_frequent_itemsets if len(itemset1 | itemset2) == len(itemset1) + 1}
|
|
|
|
|
# 计算支持度并筛选
|
|
|
|
|
new_frequent_itemsets = {itemset for itemset in candidates if calculate_support(itemset, transactions) >= min_support}
|
|
|
|
|
frequent_itemsets.extend(new_frequent_itemsets)
|
|
|
|
|
# 生成关联规则
|
|
|
|
|
for itemset in new_frequent_itemsets:
|
|
|
|
|
for subset in powerset(itemset):
|
|
|
|
|
subset = frozenset(subset)
|
|
|
|
|
diff = itemset - subset
|
|
|
|
|
if diff:
|
|
|
|
|
confidence = calculate_support(itemset, transactions) / calculate_support(subset, transactions)
|
|
|
|
|
if confidence >= min_confidence:
|
|
|
|
|
association_rules.append((subset, diff, confidence))
|
|
|
|
|
prev_frequent_itemsets = new_frequent_itemsets
|
|
|
|
|
return frequent_itemsets, association_rules
|
|
|
|
|
\`\`\`
|
|
|
|
|
### 示例和输出
|
|
|
|
|
假设我们有以下简单的购物数据集:
|
|
|
|
|
\`\`\`python
|
|
|
|
|
transactions = [
|
|
|
|
|
{'牛奶', '面包', '黄油'},
|
|
|
|
|
{'啤酒', '面包'},
|
|
|
|
|
{'牛奶', '啤酒', '黄油'},
|
|
|
|
|
{'牛奶', '鸡蛋'},
|
|
|
|
|
{'面包', '鸡蛋', '黄油'}
|
|
|
|
|
]
|
|
|
|
|
\`\`\`
|
|
|
|
|
调用Apriori算法:
|
|
|
|
|
\`\`\`python
|
|
|
|
|
min_support = 0.4
|
|
|
|
|
min_confidence = 0.5
|
|
|
|
|
frequent_itemsets, association_rules = apriori(transactions, min_support, min_confidence)
|
|
|
|
|
print("频繁项集:", frequent_itemsets)
|
|
|
|
|
print("关联规则:", association_rules)
|
|
|
|
|
\`\`\`
|
|
|
|
|
输出可能如下:
|
|
|
|
|
\`\`\`python
|
|
|
|
|
频繁项集: [{'牛奶'}, {'面包'}, {'黄油'}, {'啤酒'}, {'鸡蛋'}, {'牛奶', '面包'}, {'牛奶', '黄油'}, {'面包', '黄油'}, {'啤酒', '黄油'}, {'面包', '啤酒'}]
|
|
|
|
|
关联规则: [(('牛奶',), ('面包',), 0.6666666666666666), (('面包',), ('牛奶',), 0.6666666666666666), ...]
|
|
|
|
|
\`\`\`
|
|
|
|
|
通过这个实战应用,我们不仅学习了如何在Python中实现Apriori算法,还了解了它在购物篮分析中的具体应用。这为进一步的研究和实际应用提供了有用的指导。`);
|
|
|
|
|
const getList = () => {
|
|
|
|
|
API.selectionMetrics({ userId: JSON.parse(getUserInfo()).userId }).then((res) => {
|
|
|
|
|
res.data.forEach((element) => {
|
|
|
|
|
@ -548,6 +504,13 @@ const taskSubmit = () => {
|
|
|
|
|
dialogVisible.value = true;
|
|
|
|
|
};
|
|
|
|
|
const tableData = ref([]);
|
|
|
|
|
const codeSetting=()=>{
|
|
|
|
|
if(input.value==="购物车数据表"){
|
|
|
|
|
runResultShow2.value=true
|
|
|
|
|
}else{
|
|
|
|
|
proxy.$modal.msgWarning("请选择购物车数据表!")
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
const headerCellStyle = () => {
|
|
|
|
|
return {
|
|
|
|
|
backgroundColor: "#1882DE !important", // 设置表头背景颜色
|
|
|
|
|
@ -572,7 +535,66 @@ const optionData2 = () => {
|
|
|
|
|
tableData2.value = [];
|
|
|
|
|
tableData2.value = res.data;
|
|
|
|
|
proxy.$modal.msgSuccess("预处理成功!");
|
|
|
|
|
});
|
|
|
|
|
}).then(()=>{
|
|
|
|
|
code.value=`
|
|
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
|
import json
|
|
|
|
|
from itertools import chain, combinations
|
|
|
|
|
|
|
|
|
|
def powerset(s):
|
|
|
|
|
return chain.from_iterable(combinations(s, r) for r in range(1, len(s) + 1))
|
|
|
|
|
|
|
|
|
|
def calculate_support(itemset, transactions):
|
|
|
|
|
return sum(1 for transaction in transactions if itemset.issubset(transaction)) / len(transactions)
|
|
|
|
|
|
|
|
|
|
def apriori(transactions, min_support, min_confidence):
|
|
|
|
|
frequent_itemsets = []
|
|
|
|
|
association_rules = []
|
|
|
|
|
|
|
|
|
|
singletons = {frozenset([item]) for transaction in transactions for item in transaction}
|
|
|
|
|
singletons = {itemset for itemset in singletons if calculate_support(itemset, transactions) >= min_support}
|
|
|
|
|
frequent_itemsets.extend(singletons)
|
|
|
|
|
|
|
|
|
|
prev_frequent_itemsets = singletons
|
|
|
|
|
while prev_frequent_itemsets:
|
|
|
|
|
candidates = {itemset1 | itemset2 for itemset1 in prev_frequent_itemsets for itemset2 in prev_frequent_itemsets if len(itemset1 | itemset2) == len(itemset1) + 1}
|
|
|
|
|
new_frequent_itemsets = {itemset for itemset in candidates if calculate_support(itemset, transactions) >= min_support}
|
|
|
|
|
frequent_itemsets.extend(new_frequent_itemsets)
|
|
|
|
|
|
|
|
|
|
for itemset in new_frequent_itemsets:
|
|
|
|
|
for subset in powerset(itemset):
|
|
|
|
|
subset = frozenset(subset)
|
|
|
|
|
diff = itemset - subset
|
|
|
|
|
if diff:
|
|
|
|
|
confidence = calculate_support(itemset, transactions) / calculate_support(subset, transactions)
|
|
|
|
|
if confidence >= min_confidence:
|
|
|
|
|
rule = {
|
|
|
|
|
"correlation": list(subset),
|
|
|
|
|
"associated": list(diff),
|
|
|
|
|
"confidenceLevel": round(confidence, 2),
|
|
|
|
|
"rule": f"[{', '.join(subset)}]==>[{', '.join(diff)}]==>{round(confidence, 2)}"
|
|
|
|
|
}
|
|
|
|
|
association_rules.append(rule)
|
|
|
|
|
|
|
|
|
|
prev_frequent_itemsets = new_frequent_itemsets
|
|
|
|
|
|
|
|
|
|
result = {
|
|
|
|
|
# "frequentItemsets": [list(itemset) for itemset in frequent_itemsets],
|
|
|
|
|
"associationRules": association_rules
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
print(json.dumps(result, ensure_ascii=False))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
transactions = [
|
|
|
|
|
${resTable2.value.map(item => "{" + item.consumer_goods.split(',').map(good => "'" + good + "'").join(',') + "}").join(',')}
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
min_support = ___
|
|
|
|
|
min_confidence = ___
|
|
|
|
|
apriori(transactions, min_support, min_confidence)
|
|
|
|
|
`
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
@ -585,25 +607,31 @@ const computation = () => {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (input5.value && input6.value && input4.value) {
|
|
|
|
|
const sendData = {
|
|
|
|
|
confidence: parseFloat(input5.value) / 100,
|
|
|
|
|
support: parseFloat(input6.value) / 100,
|
|
|
|
|
userId: JSON.parse(getUserInfo()).userId,
|
|
|
|
|
deduplicatedDataList: resTable2.value,
|
|
|
|
|
};
|
|
|
|
|
API.associationRuleMining(sendData)
|
|
|
|
|
const sendData =ref({
|
|
|
|
|
minConfidence: parseFloat(input6.value) / 100,
|
|
|
|
|
minSupport: parseFloat(input5.value) / 100,
|
|
|
|
|
type: input.value,
|
|
|
|
|
data: Object.keys(resTable2.value[0]).reduce((acc, key) => {
|
|
|
|
|
acc[key] = resTable2.value.map(item => item[key]);
|
|
|
|
|
return acc;
|
|
|
|
|
}, {}),
|
|
|
|
|
})
|
|
|
|
|
if(input.value==="购物车数据表"){
|
|
|
|
|
sendData.value.data = {consumer_goods:resTable2.value.map(item => item.consumer_goods.split(','))}
|
|
|
|
|
}
|
|
|
|
|
API.associationRuleMining(sendData.value)
|
|
|
|
|
.then((res) => {
|
|
|
|
|
loading1.value = true;
|
|
|
|
|
uplodFlag.value = true;
|
|
|
|
|
tableData3.value = [];
|
|
|
|
|
tableLabel2.length = 0;
|
|
|
|
|
for (const key in res.data[0]) {
|
|
|
|
|
for (const key in res.data.associationRules[0]) {
|
|
|
|
|
tableLabel2.push({
|
|
|
|
|
label: key,
|
|
|
|
|
prop: key,
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
tableData3.value = res.data;
|
|
|
|
|
tableData3.value = res.data.associationRules;
|
|
|
|
|
//一秒后执行
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
loading1.value = false;
|
|
|
|
|
|