协同过滤算法

70 阅读14分钟

1. 请描述这个项目中协同过滤算法的整体架构设计,包括数据模型和算法流程。

答案: 项目采用了基于物品的协同过滤算法,整体架构设计如下:

数据模型设计 (recommender.ts):

interface Product {
    id: number;        // 产品唯一标识
    title: string;     // 产品标题
    likes: number;     // 点赞数(用户行为数据)
    category: string;  // 产品类别
}

export class Recommender {
    private products: Product[];           // 产品数据集合
    private similarityMatrix: number[][]; // 相似度矩阵
}

算法流程

  1. 初始化阶段
constructor(products: Product[]) {
    this.products = products;
    this.similarityMatrix = this.calculateSimilarityMatrix();
}
  1. 相似度矩阵计算
private calculateSimilarityMatrix(): number[][] {
    const n = this.products.length;
    const matrix: number[][] = Array(n).fill(0).map(() => Array(n).fill(0));

    for (let i = 0; i < n; i++) {
        for (let j = i + 1; j < n; j++) {
            const similarity = this.calculateSimilarity(this.products[i], this.products[j]);
            matrix[i][j] = similarity;
            matrix[j][i] = similarity; // 对称矩阵
        }
        matrix[i][i] = 1; // 对角线为1
    }
    return matrix;
}
  1. 推荐生成
public getRecommendations(productId: number, numRecommendations: number = 3): Product[] {
    const productIndex = this.products.findIndex(p => p.id === productId);
    if (productIndex === -1) return [];

    const similarities = this.similarityMatrix[productIndex];
    return this.products
        .map((product, index) => ({ product, similarity: similarities[index] }))
        .filter(item => item.product.id !== productId)
        .sort((a, b) => b.similarity - a.similarity)
        .slice(0, numRecommendations)
        .map(item => item.product);
}

架构优势

  • 预计算相似度矩阵,提高推荐效率
  • 支持实时推荐更新
  • 易于扩展和优化

2. 项目中的协同过滤算法是如何计算产品相似度的?请详细分析其相似度计算策略。

答案: 项目采用了多维度特征融合的相似度计算策略:

相似度计算实现

private calculateSimilarity(product1: Product, product2: Product): number {
    // 基于点赞数的相似度计算
    const likeSimilarity = 1 - Math.abs(product1.likes - product2.likes) / Math.max(product1.likes, product2.likes);
    
    // 基于类别的相似度计算
    const categorySimilarity = product1.category === product2.category ? 1 : 0;
    
    // 综合相似度(点赞权重0.7,类别权重0.3)
    return 0.7 * likeSimilarity + 0.3 * categorySimilarity;
}

计算策略分析

  1. 点赞数相似度

    • 使用归一化的差值计算:1 - |likes1 - likes2| / max(likes1, likes2)
    • 点赞数越接近,相似度越高
    • 避免了数据量级差异的影响
  2. 类别相似度

    • 布尔型计算:同类产品相似度为1,不同类为0
    • 体现了产品的分类特征
  3. 权重融合

    • 点赞权重0.7:反映用户行为偏好
    • 类别权重0.3:反映产品属性特征
    • 可根据业务需求调整权重

优化建议

// 更精细的相似度计算
private calculateSimilarity(product1: Product, product2: Product): number {
    // 点赞数相似度(使用对数归一化)
    const logLikes1 = Math.log(product1.likes + 1);
    const logLikes2 = Math.log(product2.likes + 1);
    const likeSimilarity = 1 - Math.abs(logLikes1 - logLikes2) / Math.max(logLikes1, logLikes2);
    
    // 类别相似度
    const categorySimilarity = product1.category === product2.category ? 1 : 0;
    
    // 价格相似度(如果有价格数据)
    const priceSimilarity = 1 - Math.abs(product1.price - product2.price) / Math.max(product1.price, product2.price);
    
    // 多维度加权
    return 0.5 * likeSimilarity + 0.3 * categorySimilarity + 0.2 * priceSimilarity;
}

3. 项目中的协同过滤算法是如何与热门推荐算法结合的?请分析其混合推荐策略。

答案: 项目采用了协同过滤与热门推荐相结合的混合推荐策略:

混合推荐实现 (Product.vue):

// 更新推荐
const updateRecommendations = (product: any) => {
    const recommender = new Recommender(looplist.value)
    
    // 协同过滤推荐
    const cfRecommendations = recommender.getRecommendations(product.id) || []
    
    // 热门推荐(排除当前产品)
    const hotRecommendations = looplist.value
        .filter((item) => item.id !== product.id)
        .sort((a, b) => b.likes - a.likes)
        .slice(0, 5)
    
    // 合并去重
    const merged = [...cfRecommendations, ...hotRecommendations]
    const uniqueMap = new Map()
    merged.forEach((item) => {
        if (!uniqueMap.has(item.id)) {
            uniqueMap.set(item.id, item)
        }
    })
    
    // 只取前三个
    recommendedProducts.value = Array.from(uniqueMap.values()).slice(0, 3)
}

混合策略分析

  1. 协同过滤优势

    • 基于用户行为数据
    • 个性化程度高
    • 能发现长尾产品
  2. 热门推荐优势

    • 推荐质量稳定
    • 覆盖度高
    • 冷启动友好
  3. 混合策略优势

    • 平衡个性化和流行度
    • 提高推荐多样性
    • 降低冷启动问题

优化方案

// 加权混合推荐
const updateRecommendations = (product: any) => {
    const recommender = new Recommender(looplist.value)
    
    // 协同过滤推荐
    const cfRecommendations = recommender.getRecommendations(product.id, 5)
    
    // 热门推荐
    const hotRecommendations = looplist.value
        .filter((item) => item.id !== product.id)
        .sort((a, b) => b.likes - a.likes)
        .slice(0, 5)
    
    // 加权合并
    const weightedRecommendations = []
    
    // 协同过滤权重0.6
    cfRecommendations.forEach((item, index) => {
        weightedRecommendations.push({
            ...item,
            score: 0.6 * (1 - index * 0.1) // 递减权重
        })
    })
    
    // 热门推荐权重0.4
    hotRecommendations.forEach((item, index) => {
        const existing = weightedRecommendations.find(r => r.id === item.id)
        if (existing) {
            existing.score += 0.4 * (1 - index * 0.1)
        } else {
            weightedRecommendations.push({
                ...item,
                score: 0.4 * (1 - index * 0.1)
            })
        }
    })
    
    // 按得分排序
    recommendedProducts.value = weightedRecommendations
        .sort((a, b) => b.score - a.score)
        .slice(0, 3)
        .map(item => ({ ...item, score: undefined }))
}

4. 项目中的协同过滤算法是如何处理数据更新和实时推荐的?请分析其更新机制。

答案: 项目实现了基于用户行为的实时推荐更新机制:

实时更新触发

// 处理点赞
const handleLike = async (item: any) => {
    if (item.likeLoading) return

    item.likeLoading = true
    try {
        await new Promise((resolve) => setTimeout(resolve, 500))
        item.isLiked = !item.isLiked
        item.likes = item.isLiked ? item.likes + 1 : item.likes - 1

        // 更新推荐
        if (selectedProduct.value) {
            updateRecommendations(selectedProduct.value)
        }

        ElMessage.success(item.isLiked ? '点赞成功' : '取消点赞')
    } catch (error) {
        ElMessage.error('操作失败,请稍后重试')
    } finally {
        item.likeLoading = false
    }
}

更新机制分析

  1. 用户行为触发

    • 点赞/取消点赞操作
    • 产品选择操作
    • 实时更新推荐结果
  2. 数据更新流程

// 选择产品触发推荐更新
const selectProduct = (product: any) => {
    selectedProduct.value = product
    updateRecommendations(product)
}
  1. 推荐器重新初始化
const updateRecommendations = (product: any) => {
    // 每次更新都重新创建推荐器,确保数据最新
    const recommender = new Recommender(looplist.value)
    const cfRecommendations = recommender.getRecommendations(product.id) || []
    // ... 后续处理
}

性能优化建议

// 缓存优化版本
class CachedRecommender {
    private cache = new Map()
    private lastUpdate = 0
    private updateInterval = 5000 // 5秒更新一次

    public getRecommendations(productId: number, products: Product[]): Product[] {
        const now = Date.now()
        
        // 检查缓存是否有效
        if (this.cache.has(productId) && (now - this.lastUpdate) < this.updateInterval) {
            return this.cache.get(productId)
        }
        
        // 重新计算
        const recommender = new Recommender(products)
        const recommendations = recommender.getRecommendations(productId)
        
        // 更新缓存
        this.cache.set(productId, recommendations)
        this.lastUpdate = now
        
        return recommendations
    }
    
    // 清除缓存
    public clearCache() {
        this.cache.clear()
        this.lastUpdate = 0
    }
}

5. 项目中的协同过滤算法在冷启动问题上是如何处理的?请分析其解决方案。

答案: 项目通过多种策略来解决冷启动问题:

冷启动问题分析

  1. 新用户冷启动:用户没有行为数据
  2. 新产品冷启动:产品没有用户行为数据
  3. 稀疏数据问题:数据量少,相似度计算不准确

解决方案

  1. 热门推荐兜底
const updateRecommendations = (product: any) => {
    const recommender = new Recommender(looplist.value)
    
    // 协同过滤推荐
    const cfRecommendations = recommender.getRecommendations(product.id) || []
    
    // 热门推荐作为兜底
    const hotRecommendations = looplist.value
        .filter((item) => item.id !== product.id)
        .sort((a, b) => b.likes - a.likes)
        .slice(0, 5)
    
    // 如果协同过滤推荐不足,用热门推荐补充
    const finalRecommendations = cfRecommendations.length >= 3 
        ? cfRecommendations 
        : [...cfRecommendations, ...hotRecommendations]
    
    recommendedProducts.value = finalRecommendations.slice(0, 3)
}
  1. 基于内容的推荐
// 基于产品属性的推荐
const getContentBasedRecommendations = (product: any, products: any[]) => {
    return products
        .filter(item => item.id !== product.id)
        .map(item => ({
            ...item,
            similarity: calculateContentSimilarity(product, item)
        }))
        .sort((a, b) => b.similarity - a.similarity)
        .slice(0, 3)
        .map(item => ({ ...item, similarity: undefined }))
}

const calculateContentSimilarity = (product1: any, product2: any) => {
    let similarity = 0
    
    // 类别相似度
    if (product1.category === product2.category) {
        similarity += 0.4
    }
    
    // 价格相似度
    const priceDiff = Math.abs(product1.price - product2.price) / Math.max(product1.price, product2.price)
    similarity += 0.3 * (1 - priceDiff)
    
    // 产地相似度
    if (product1.origin === product2.origin) {
        similarity += 0.3
    }
    
    return similarity
}
  1. 混合推荐策略
const getHybridRecommendations = (product: any, products: any[]) => {
    const recommender = new Recommender(products)
    const cfRecommendations = recommender.getRecommendations(product.id)
    
    // 如果协同过滤推荐不足,使用内容推荐
    if (cfRecommendations.length < 3) {
        const contentRecommendations = getContentBasedRecommendations(product, products)
        const hotRecommendations = products
            .filter(item => item.id !== product.id)
            .sort((a, b) => b.likes - a.likes)
            .slice(0, 3)
        
        return [...cfRecommendations, ...contentRecommendations, ...hotRecommendations]
            .filter((item, index, arr) => arr.findIndex(i => i.id === item.id) === index)
            .slice(0, 3)
    }
    
    return cfRecommendations
}

6. 项目中的协同过滤算法在相似度矩阵计算上有什么优化空间?请分析其性能优化方案。

答案: 当前的相似度矩阵计算存在性能优化空间,以下是具体的优化方案:

当前实现分析

private calculateSimilarityMatrix(): number[][] {
    const n = this.products.length;
    const matrix: number[][] = Array(n).fill(0).map(() => Array(n).fill(0));

    for (let i = 0; i < n; i++) {
        for (let j = i + 1; j < n; j++) {
            const similarity = this.calculateSimilarity(this.products[i], this.products[j]);
            matrix[i][j] = similarity;
            matrix[j][i] = similarity;
        }
        matrix[i][i] = 1;
    }
    return matrix;
}

性能问题

  • 时间复杂度:O(n²)
  • 空间复杂度:O(n²)
  • 每次数据更新都需要重新计算

优化方案

  1. 稀疏矩阵优化
class SparseRecommender {
    private similarityMap = new Map<string, number>()
    
    private calculateSimilarityMatrix(): void {
        const n = this.products.length;
        
        for (let i = 0; i < n; i++) {
            for (let j = i + 1; j < n; j++) {
                const similarity = this.calculateSimilarity(this.products[i], this.products[j]);
                if (similarity > 0.1) { // 只存储相似度大于0.1的
                    const key = `${i}-${j}`;
                    this.similarityMap.set(key, similarity);
                }
            }
        }
    }
    
    private getSimilarity(i: number, j: number): number {
        if (i === j) return 1;
        if (i > j) [i, j] = [j, i]; // 确保i < j
        return this.similarityMap.get(`${i}-${j}`) || 0;
    }
}
  1. 增量更新机制
class IncrementalRecommender {
    private similarityMatrix: number[][];
    private lastUpdateTime = 0;
    
    public updateProductLikes(productId: number, newLikes: number): void {
        const productIndex = this.products.findIndex(p => p.id === productId);
        if (productIndex === -1) return;
        
        // 只更新相关行和列
        this.updateSimilarityRow(productIndex, newLikes);
        this.updateSimilarityColumn(productIndex, newLikes);
    }
    
    private updateSimilarityRow(rowIndex: number, newLikes: number): void {
        for (let j = 0; j < this.products.length; j++) {
            if (rowIndex !== j) {
                const similarity = this.calculateSimilarity(
                    { ...this.products[rowIndex], likes: newLikes },
                    this.products[j]
                );
                this.similarityMatrix[rowIndex][j] = similarity;
                this.similarityMatrix[j][rowIndex] = similarity;
            }
        }
    }
}
  1. 并行计算优化
class ParallelRecommender {
    private async calculateSimilarityMatrix(): Promise<number[][]> {
        const n = this.products.length;
        const matrix: number[][] = Array(n).fill(0).map(() => Array(n).fill(0));
        
        // 并行计算相似度
        const promises: Promise<void>[] = [];
        
        for (let i = 0; i < n; i++) {
            for (let j = i + 1; j < n; j++) {
                promises.push(this.calculateSimilarityAsync(i, j, matrix));
            }
        }
        
        await Promise.all(promises);
        
        // 填充对角线
        for (let i = 0; i < n; i++) {
            matrix[i][i] = 1;
        }
        
        return matrix;
    }
    
    private async calculateSimilarityAsync(i: number, j: number, matrix: number[][]): Promise<void> {
        const similarity = this.calculateSimilarity(this.products[i], this.products[j]);
        matrix[i][j] = similarity;
        matrix[j][i] = similarity;
    }
}
  1. 缓存策略优化
class CachedRecommender {
    private cache = new Map<string, number>();
    private cacheTimeout = 300000; // 5分钟缓存
    
    private calculateSimilarity(product1: Product, product2: Product): number {
        const cacheKey = `${product1.id}-${product2.id}`;
        
        if (this.cache.has(cacheKey)) {
            const cached = this.cache.get(cacheKey);
            if (cached && Date.now() - cached.timestamp < this.cacheTimeout) {
                return cached.value;
            }
        }
        
        const similarity = this.computeSimilarity(product1, product2);
        this.cache.set(cacheKey, {
            value: similarity,
            timestamp: Date.now()
        });
        
        return similarity;
    }
}

7. 项目中的协同过滤算法是如何处理数据稀疏性和噪声问题的?请分析其数据预处理策略。

答案: 项目通过多种数据预处理策略来处理稀疏性和噪声问题:

数据稀疏性问题分析

  • 产品数量有限(20个产品)
  • 用户行为数据单一(只有点赞数)
  • 相似度计算可能不够准确

数据预处理策略

  1. 数据标准化
class DataPreprocessor {
    private normalizeLikes(products: Product[]): Product[] {
        const likes = products.map(p => p.likes);
        const minLikes = Math.min(...likes);
        const maxLikes = Math.max(...likes);
        
        return products.map(product => ({
            ...product,
            normalizedLikes: (product.likes - minLikes) / (maxLikes - minLikes)
        }));
    }
    
    private handleZeroLikes(products: Product[]): Product[] {
        return products.map(product => ({
            ...product,
            likes: product.likes === 0 ? 1 : product.likes // 避免除零错误
        }));
    }
}
  1. 噪声过滤
class NoiseFilter {
    private filterOutliers(products: Product[]): Product[] {
        const likes = products.map(p => p.likes);
        const mean = likes.reduce((a, b) => a + b, 0) / likes.length;
        const std = Math.sqrt(likes.reduce((sq, n) => sq + Math.pow(n - mean, 2), 0) / likes.length);
        
        return products.filter(product => {
            const zScore = Math.abs((product.likes - mean) / std);
            return zScore < 3; // 过滤3个标准差以外的异常值
        });
    }
    
    private smoothData(products: Product[]): Product[] {
        return products.map(product => ({
            ...product,
            smoothedLikes: Math.log(product.likes + 1) // 对数平滑
        }));
    }
}
  1. 相似度阈值过滤
class SimilarityFilter {
    private calculateSimilarityWithThreshold(product1: Product, product2: Product): number {
        const rawSimilarity = this.calculateRawSimilarity(product1, product2);
        
        // 设置最小相似度阈值
        const threshold = 0.1;
        return rawSimilarity > threshold ? rawSimilarity : 0;
    }
    
    private getRecommendationsWithFilter(productId: number, numRecommendations: number = 3): Product[] {
        const productIndex = this.products.findIndex(p => p.id === productId);
        if (productIndex === -1) return [];

        const similarities = this.similarityMatrix[productIndex];
        const recommendations = this.products
            .map((product, index) => ({
                product,
                similarity: similarities[index]
            }))
            .filter(item => 
                item.product.id !== productId && 
                item.similarity > 0.1 // 过滤低相似度产品
            )
            .sort((a, b) => b.similarity - a.similarity)
            .slice(0, numRecommendations)
            .map(item => item.product);

        return recommendations;
    }
}
  1. 数据增强策略
class DataEnhancer {
    private enhanceProductData(products: Product[]): Product[] {
        return products.map(product => ({
            ...product,
            // 添加虚拟特征
            popularity: this.calculatePopularity(product),
            categoryWeight: this.getCategoryWeight(product.category),
            priceTier: this.getPriceTier(product.price)
        }));
    }
    
    private calculatePopularity(product: Product): number {
        // 基于点赞数和时间的综合热度
        const daysSincePublish = (Date.now() - new Date(product.publishTime).getTime()) / (1000 * 60 * 60 * 24);
        return product.likes / (daysSincePublish + 1);
    }
    
    private getCategoryWeight(category: string): number {
        const weights = {
            '水果': 1.2,
            '蔬菜': 1.0,
            '粮食': 0.8,
            '肉类': 1.1,
            '茶叶': 0.9
        };
        return weights[category] || 1.0;
    }
}
  1. 改进的相似度计算
private calculateSimilarity(product1: Product, product2: Product): number {
    // 处理零值情况
    const maxLikes = Math.max(product1.likes, product2.likes, 1);
    const likeSimilarity = 1 - Math.abs(product1.likes - product2.likes) / maxLikes;
    
    // 类别相似度
    const categorySimilarity = product1.category === product2.category ? 1 : 0;
    
    // 添加时间衰减因子
    const timeDecay = this.calculateTimeDecay(product1, product2);
    
    // 综合相似度
    return 0.6 * likeSimilarity + 0.3 * categorySimilarity + 0.1 * timeDecay;
}

private calculateTimeDecay(product1: Product, product2: Product): number {
    const time1 = new Date(product1.publishTime).getTime();
    const time2 = new Date(product2.publishTime).getTime();
    const timeDiff = Math.abs(time1 - time2) / (1000 * 60 * 60 * 24); // 天数差
    return Math.exp(-timeDiff / 30); // 30天衰减周期
}

8. 项目中的协同过滤算法是如何评估推荐质量的?请分析其评估指标和优化策略。

答案: 项目可以通过多种评估指标来衡量推荐质量,以下是具体的评估策略:

评估指标设计

  1. 准确率指标
class RecommendationEvaluator {
    // 推荐准确率
    public calculatePrecision(recommendations: Product[], userLikes: number[]): number {
        const relevantItems = recommendations.filter(item => userLikes.includes(item.id));
        return relevantItems.length / recommendations.length;
    }
    
    // 召回率
    public calculateRecall(recommendations: Product[], userLikes: number[], totalLikes: number[]): number {
        const relevantItems = recommendations.filter(item => userLikes.includes(item.id));
        return relevantItems.length / userLikes.length;
    }
    
    // F1分数
    public calculateF1Score(precision: number, recall: number): number {
        return 2 * (precision * recall) / (precision + recall);
    }
}
  1. 多样性指标
class DiversityEvaluator {
    // 推荐多样性
    public calculateDiversity(recommendations: Product[]): number {
        const categories = new Set(recommendations.map(item => item.category));
        return categories.size / recommendations.length;
    }
    
    // 推荐新颖性
    public calculateNovelty(recommendations: Product[], popularItems: number[]): number {
        const novelItems = recommendations.filter(item => !popularItems.includes(item.id));
        return novelItems.length / recommendations.length;
    }
    
    // 覆盖率
    public calculateCoverage(recommendations: Product[], totalItems: Product[]): number {
        const recommendedIds = new Set(recommendations.map(item => item.id));
        return recommendedIds.size / totalItems.length;
    }
}
  1. 用户满意度指标
class UserSatisfactionEvaluator {
    // 点击率
    public calculateClickThroughRate(recommendations: Product[], clicks: number[]): number {
        const clickedItems = recommendations.filter(item => clicks.includes(item.id));
        return clickedItems.length / recommendations.length;
    }
    
    // 停留时间
    public calculateAverageDwellTime(recommendations: Product[], dwellTimes: Map<number, number>): number {
        const totalTime = recommendations.reduce((sum, item) => {
            return sum + (dwellTimes.get(item.id) || 0);
        }, 0);
        return totalTime / recommendations.length;
    }
}

在线评估实现

class OnlineEvaluator {
    private metrics = {
        precision: 0,
        recall: 0,
        diversity: 0,
        clickThroughRate: 0
    };
    
    public evaluateRecommendation(recommendations: Product[], userAction: any): void {
        // 实时更新评估指标
        this.updatePrecision(recommendations, userAction);
        this.updateDiversity(recommendations);
        this.updateClickThroughRate(recommendations, userAction);
    }
    
    public getEvaluationReport(): any {
        return {
            ...this.metrics,
            timestamp: new Date().toISOString()
        };
    }
}

A/B测试框架

class ABTestFramework {
    private variants = {
        'cf_only': new Recommender(this.products),
        'hybrid': new HybridRecommender(this.products),
        'content_based': new ContentBasedRecommender(this.products)
    };
    
    public getRecommendations(userId: string, productId: number): Product[] {
        // 根据用户ID分配测试组
        const variant = this.assignVariant(userId);
        return this.variants[variant].getRecommendations(productId);
    }
    
    private assignVariant(userId: string): string {
        const hash = this.hashCode(userId);
        const group = hash % 3;
        
        switch (group) {
            case 0: return 'cf_only';
            case 1: return 'hybrid';
            case 2: return 'content_based';
            default: return 'hybrid';
        }
    }
    
    public trackUserAction(userId: string, action: string, productId: number): void {
        // 记录用户行为用于评估
        this.logUserAction(userId, action, productId);
    }
}

优化策略

class AdaptiveRecommender {
    private performanceHistory: any[] = [];
    
    public adaptiveRecommendation(productId: number): Product[] {
        const recentPerformance = this.getRecentPerformance();
        
        if (recentPerformance.precision < 0.3) {
            // 准确率低,增加热门推荐权重
            return this.getHotRecommendations(productId);
        } else if (recentPerformance.diversity < 0.5) {
            // 多样性低,增加类别多样性
            return this.getDiverseRecommendations(productId);
        } else {
            // 性能良好,使用标准推荐
            return this.getStandardRecommendations(productId);
        }
    }
    
    private getRecentPerformance(): any {
        const recent = this.performanceHistory.slice(-10);
        return {
            precision: recent.reduce((sum, p) => sum + p.precision, 0) / recent.length,
            diversity: recent.reduce((sum, p) => sum + p.diversity, 0) / recent.length
        };
    }
}

9. 项目中的协同过滤算法是如何处理用户偏好变化的?请分析其动态适应策略。

答案: 项目通过多种策略来处理用户偏好的动态变化:

用户偏好变化检测

  1. 时间衰减机制
class TimeAwareRecommender {
    private calculateTimeDecaySimilarity(product1: Product, product2: Product): number {
        const baseSimilarity = this.calculateBaseSimilarity(product1, product2);
        const timeDecay = this.calculateTimeDecay(product1, product2);
        return baseSimilarity * timeDecay;
    }
    
    private calculateTimeDecay(product1: Product, product2: Product): number {
        const now = Date.now();
        const time1 = new Date(product1.publishTime).getTime();
        const time2 = new Date(product2.publishTime).getTime();
        
        // 计算时间差(天数)
        const daysDiff = Math.abs(time1 - time2) / (1000 * 60 * 60 * 24);
        
        // 指数衰减,30天为半衰期
        return Math.exp(-daysDiff / 30);
    }
}
  1. 滑动窗口机制
class SlidingWindowRecommender {
    private windowSize = 30; // 30天窗口
    private userActions: Map<string, any[]> = new Map();
    
    public addUserAction(userId: string, action: any): void {
        if (!this.userActions.has(userId)) {
            this.userActions.set(userId, []);
        }
        
        const actions = this.userActions.get(userId);
        actions.push({
            ...action,
            timestamp: Date.now()
        });
        
        // 清理过期数据
        this.cleanOldActions(userId);
    }
    
    private cleanOldActions(userId: string): void {
        const actions = this.userActions.get(userId);
        const cutoffTime = Date.now() - (this.windowSize * 24 * 60 * 60 * 1000);
        
        const filteredActions = actions.filter(action => action.timestamp > cutoffTime);
        this.userActions.set(userId, filteredActions);
    }
    
    public getRecentPreferences(userId: string): any[] {
        const actions = this.userActions.get(userId) || [];
        return actions.sort((a, b) => b.timestamp - a.timestamp);
    }
}
  1. 动态权重调整
class AdaptiveWeightRecommender {
    private weights = {
        recent: 0.6,    // 最近行为权重
        historical: 0.3, // 历史行为权重
        category: 0.1   // 类别偏好权重
    };
    
    public updateWeights(userId: string): void {
        const recentActions = this.getRecentActions(userId, 7); // 最近7天
        const historicalActions = this.getHistoricalActions(userId);
        
        // 根据行为变化调整权重
        const recentActivity = recentActions.length;
        const historicalActivity = historicalActions.length;
        
        if (recentActivity > historicalActivity * 0.5) {
            // 用户活跃,增加最近权重
            this.weights.recent = 0.7;
            this.weights.historical = 0.2;
            this.weights.category = 0.1;
        } else {
            // 用户不活跃,增加历史权重
            this.weights.recent = 0.4;
            this.weights.historical = 0.5;
            this.weights.category = 0.1;
        }
    }
    
    private calculateAdaptiveSimilarity(product1: Product, product2: Product, userId: string): number {
        const recentSimilarity = this.calculateRecentSimilarity(product1, product2, userId);
        const historicalSimilarity = this.calculateHistoricalSimilarity(product1, product2, userId);
        const categorySimilarity = this.calculateCategorySimilarity(product1, product2);
        
        return this.weights.recent * recentSimilarity +
               this.weights.historical * historicalSimilarity +
               this.weights.category * categorySimilarity;
    }
}
  1. 偏好漂移检测
class PreferenceDriftDetector {
    private userPreferences: Map<string, any[]> = new Map();
    
    public detectPreferenceDrift(userId: string): boolean {
        const preferences = this.userPreferences.get(userId) || [];
        if (preferences.length < 10) return false; // 数据不足
        
        const recent = preferences.slice(-5);
        const historical = preferences.slice(0, -5);
        
        const recentCategories = new Set(recent.map(p => p.category));
        const historicalCategories = new Set(historical.map(p => p.category));
        
        // 计算类别变化程度
        const intersection = new Set([...recentCategories].filter(x => historicalCategories.has(x)));
        const union = new Set([...recentCategories, ...historicalCategories]);
        
        const jaccardSimilarity = intersection.size / union.size;
        
        return jaccardSimilarity < 0.3; // 相似度低于0.3认为有偏好漂移
    }
    
    public handlePreferenceDrift(userId: string): void {
        // 检测到偏好漂移时的处理策略
        if (this.detectPreferenceDrift(userId)) {
            // 增加探索性推荐
            this.increaseExploration(userId);
            // 重置用户模型
            this.resetUserModel(userId);
        }
    }
    
    private increaseExploration(userId: string): void {
        // 增加推荐多样性,引入更多新类别
        const explorationRate = 0.3; // 30%的探索性推荐
        // 实现探索性推荐逻辑
    }
}
  1. 实时反馈机制
class RealTimeFeedbackRecommender {
    private feedbackQueue: any[] = [];
    
    public addFeedback(userId: string, productId: number, feedback: string): void {
        this.feedbackQueue.push({
            userId,
            productId,
            feedback,
            timestamp: Date.now()
        });
        
        // 处理反馈
        this.processFeedback();
    }
    
    private processFeedback(): void {
        const recentFeedback = this.feedbackQueue
            .filter(f => Date.now() - f.timestamp < 60000) // 最近1分钟
            .slice(-10); // 最近10条
        
        if (recentFeedback.length >= 5) {
            // 有足够反馈时更新推荐策略
            this.updateRecommendationStrategy(recentFeedback);
        }
    }
    
    private updateRecommendationStrategy(feedback: any[]): void {
        const positiveFeedback = feedback.filter(f => f.feedback === 'positive');
        const negativeFeedback = feedback.filter(f => f.feedback === 'negative');
        
        if (negativeFeedback.length > positiveFeedback.length) {
            // 负面反馈多,调整推荐策略
            this.adjustRecommendationWeights();
        }
    }
}

10. 项目中的协同过滤算法在未来扩展性方面有哪些改进空间?请分析其架构优化方案。

答案: 项目的协同过滤算法在扩展性方面有多个改进空间,以下是具体的优化方案:

当前架构限制分析

  1. 数据规模限制:当前只有20个产品
  2. 算法复杂度:O(n²)的相似度矩阵计算
  3. 实时性限制:每次更新都重新计算
  4. 特征单一:只使用点赞数和类别

扩展性优化方案

  1. 分布式计算架构
class DistributedRecommender {
    private workers: Worker[] = [];
    private chunkSize = 1000; // 每个worker处理1000个产品
    
    public async calculateSimilarityMatrix(products: Product[]): Promise<number[][]> {
        const chunks = this.chunkProducts(products);
        const promises = chunks.map((chunk, index) => 
            this.calculateChunkSimilarity(chunk, index)
        );
        
        const results = await Promise.all(promises);
        return this.mergeResults(results, products.length);
    }
    
    private chunkProducts(products: Product[]): Product[][] {
        const chunks = [];
        for (let i = 0; i < products.length; i += this.chunkSize) {
            chunks.push(products.slice(i, i + this.chunkSize));
        }
        return chunks;
    }
    
    private async calculateChunkSimilarity(chunk: Product[], chunkIndex: number): Promise<any> {
        return new Promise((resolve) => {
            const worker = new Worker('/workers/similarity-worker.js');
            worker.postMessage({ chunk, chunkIndex });
            worker.onmessage = (e) => resolve(e.data);
        });
    }
}
  1. 增量计算架构
class IncrementalRecommender {
    private similarityCache = new Map<string, number>();
    private updateQueue: any[] = [];
    
    public async processUpdates(): Promise<void> {
        while (this.updateQueue.length > 0) {
            const batch = this.updateQueue.splice(0, 10); // 批量处理10个更新
            await this.processBatch(batch);
        }
    }
    
    private async processBatch(updates: any[]): Promise<void> {
        const affectedProducts = new Set();
        
        // 收集受影响的产品
        updates.forEach(update => {
            affectedProducts.add(update.productId);
        });
        
        // 只重新计算受影响产品的相似度
        for (const productId of affectedProducts) {
            await this.recalculateProductSimilarity(productId);
        }
    }
    
    private async recalculateProductSimilarity(productId: number): Promise<void> {
        const product = this.products.find(p => p.id === productId);
        if (!product) return;
        
        // 只更新该产品与其他产品的相似度
        for (const otherProduct of this.products) {
            if (otherProduct.id !== productId) {
                const similarity = this.calculateSimilarity(product, otherProduct);
                const key = `${Math.min(productId, otherProduct.id)}-${Math.max(productId, otherProduct.id)}`;
                this.similarityCache.set(key, similarity);
            }
        }
    }
}
  1. 特征工程扩展
class FeatureEngine {
    private features = {
        // 基础特征
        likes: (product: Product) => product.likes,
        category: (product: Product) => product.category,
        
        // 扩展特征
        popularity: (product: Product) => this.calculatePopularity(product),
        price: (product: Product) => product.price,
        origin: (product: Product) => product.origin,
        publishTime: (product: Product) => new Date(product.publishTime).getTime(),
        
        // 用户行为特征
        viewCount: (product: Product) => product.viewCount || 0,
        purchaseCount: (product: Product) => product.purchaseCount || 0,
        rating: (product: Product) => product.rating || 0,
        
        // 内容特征
        titleLength: (product: Product) => product.title.length,
        descriptionLength: (product: Product) => product.introduction.length,
        
        // 时间特征
        daysSincePublish: (product: Product) => {
            const publishDate = new Date(product.publishTime);
            const now = new Date();
            return (now.getTime() - publishDate.getTime()) / (1000 * 60 * 60 * 24);
        }
    };
    
    public extractFeatures(product: Product): number[] {
        return Object.values(this.features).map(feature => feature(product));
    }
    
    public calculateFeatureSimilarity(features1: number[], features2: number[]): number {
        // 使用余弦相似度
        const dotProduct = features1.reduce((sum, val, i) => sum + val * features2[i], 0);
        const norm1 = Math.sqrt(features1.reduce((sum, val) => sum + val * val, 0));
        const norm2 = Math.sqrt(features2.reduce((sum, val) => sum + val * val, 0));
        
        return dotProduct / (norm1 * norm2);
    }
}
  1. 多算法融合架构
class EnsembleRecommender {
    private algorithms = {
        collaborative: new CollaborativeFilter(),
        contentBased: new ContentBasedFilter(),
        popularity: new PopularityFilter(),
        timeBased: new TimeBasedFilter()
    };
    
    private weights = {
        collaborative: 0.4,
        contentBased: 0.3,
        popularity: 0.2,
        timeBased: 0.1
    };
    
    public async getRecommendations(productId: number): Promise<Product[]> {
        const recommendations = await Promise.all([
            this.algorithms.collaborative.getRecommendations(productId),
            this.algorithms.contentBased.getRecommendations(productId),
            this.algorithms.popularity.getRecommendations(productId),
            this.algorithms.timeBased.getRecommendations(productId)
        ]);
        
        return this.ensembleRecommendations(recommendations);
    }
    
    private ensembleRecommendations(recommendations: Product[][]): Product[] {
        const scores = new Map<number, number>();
        
        recommendations.forEach((recs, index) => {
            const weight = Object.values(this.weights)[index];
            recs.forEach((product, rank) => {
                const currentScore = scores.get(product.id) || 0;
                scores.set(product.id, currentScore + weight * (1 / (rank + 1)));
            });
        });
        
        return Array.from(scores.entries())
            .sort((a, b) => b[1] - a[1])
            .slice(0, 3)
            .map(([id]) => this.products.find(p => p.id === id))
            .filter(Boolean);
    }
}
  1. 缓存和预计算架构
class CachedRecommender {
    private cache = new Map<string, { data: Product[], timestamp: number }>();
    private cacheTimeout = 300000; // 5分钟
    
    public async getRecommendations(productId: number): Promise<Product[]> {
        const cacheKey = `rec_${productId}`;
        const cached = this.cache.get(cacheKey);
        
        if (cached && Date.now() - cached.timestamp < this.cacheTimeout) {
            return cached.data;
        }
        
        const recommendations = await this.calculateRecommendations(productId);
        this.cache.set(cacheKey, {
            data: recommendations,
            timestamp: Date.now()
        });
        
        return recommendations;
    }
    
    public precomputeRecommendations(): void {
        // 预计算所有产品的推荐
        this.products.forEach(async (product) => {
            const recommendations = await this.calculateRecommendations(product.id);
            const cacheKey = `rec_${product.id}`;
            this.cache.set(cacheKey, {
                data: recommendations,
                timestamp: Date.now()
            });
        });
    }
}