24、Twitter好友推荐引擎与支持向量机模型的应用与优化

Twitter好友推荐引擎与支持向量机模型的应用与优化

一、Twitter好友推荐引擎构建

1.1 Twitter用户社区结构

在Twitter网络中,用户呈现出不同的社区结构。以Drew的网络为例,蓝色分区的用户分布较为分散,一部分靠近Drew和网络左侧,他们主要关注国家安全领域中技术的作用,比如Sean Gourley(sgourley)、Lewis Shepherd(lewisshepherd)和Jeffrey Carr(Jeffrey Carr);另一部分则更靠近右侧的绿色群体,这些用户更聚焦于国家安全政策,绿色群体中包含许多国家安全领域的知名人士,如Andrew Exum(abumuqawama)、Joshua Foust(joshua Foust)和Daveed Gartenstein - Ross(daveedgr)。而处于这些群体之间的用户,如Chris Albon(chrisalbon),则位于边缘位置。

1.2 构建“谁该关注”推荐引擎的思路

构建Twitter好友推荐引擎有多种方式:
- 基于推文内容 :通过文本挖掘,根据推文中的共同词汇或主题来匹配用户。
- 基于地理位置 :利用推文的地理定位数据,推荐活跃且与你地理位置相近的用户。
- 结合两者 :取上述两种方法前100个推荐结果的交集。

但这里我们基于社交网络关系来构建推荐引擎,借助Fritz Heider的“社会平衡理论”:
- 我朋友的朋友是我的朋友
- 我朋友的敌人是我的敌人
- 我敌人的朋友是我的敌人
- 我敌人的敌人是我的朋友

虽然我们没有明确的正负关系(朋友或敌人)信息,但假设在Twitter上敌人不会相互关注,那么我们可以通过寻找朋友的朋友来构建推荐。

1.3 具体实现步骤

1.3.1 数据加载
user <- "drewconway"
user.graph <- read.graph(paste("data/", user, "/", user, "_net.graphml",sep=""), 
    format="graphml")
1.3.2 获取种子用户的朋友列表
friends <- V(user.graph)$name[neighbors(user.graph, user, mode="out")+1]
user.el <- get.edgelist(user.graph)
1.3.3 筛选出种子用户未关注但朋友关注的用户
non.friends <- sapply(1:nrow(user.el), function(i) ifelse(any(user.el[i,]==user | 
    !user.el[i,1] %in% friends) | user.el[i,2] %in% friends, FALSE, TRUE))
non.friends.el <- user.el[which(non.friends==TRUE),]
friends.count <- table(non.friends.el[,2])
1.3.4 生成推荐结果
friends.followers <- data.frame(list(Twitter.Users=names(friends.count), 
    Friends.Following=as.numeric(friends.count)), stringsAsFactors=FALSE)
friends.followers$Friends.Norm <- friends.followers$Friends.Following/length(friends)
friends.followers <- friends.followers[with(friends.followers, order(-Friends.Norm)),]
1.3.5 查看前10个推荐结果
friends.followers[1:10,]

以下是Drew的部分推荐结果:
| Twitter用户 | 朋友关注数量 | 朋友关注比例 |
| — | — | — |
| cshirky | 80 | 0.3053435 |
| bigdata | 57 | 0.2175573 |
| fredwilson | 57 | 0.2175573 |
| dangerroom | 56 | 0.2137405 |
| shitmydadsays | 55 | 0.2099237 |
| al3x | 53 | 0.2022901 |
| fivethirtyeight | 52 | 0.1984733 |
| theeconomist | 52 | 0.1984733 |
| zephoria | 52 | 0.1984733 |
| cdixon | 51 | 0.1946565 |

1.4 基于社区结构的优化推荐

由于种子用户的网络存在明显的社区结构,我们可以利用这些结构来推荐更符合用户兴趣的人。具体步骤如下:

1.4.1 加载包含分区数据的自我网络
user.ego <- read.graph(paste("data/", user, "/", user, "_ego.graphml", sep=""), 
    format="graphml")
friends.partitions <- cbind(V(user.ego)$HC8, V(user.ego)$name)
1.4.2 定义查找每个分区推荐用户的函数
partition.follows <- function(i) {
    friends.in <- friends.partitions[which(friends.partitions[,1]==i),2]
    partition.non.follow <- non.friends.el[which(!is.na(match(non.friends.el[,1], friends.in))),]
    if(nrow(partition.non.follow) < 2) {
        return(c(i, NA))
    } else {
        partition.favorite <- table(partition.non.follow[,2])
        partition.favorite <- partition.favorite[order(-partition.favorite)]
        return(c(i,names(partition.favorite)[1]))
    }
}
1.4.3 生成按分区的推荐结果
partition.recs <- t(sapply(unique(friends.partitions[,1]), partition.follows))
partition.recs <- partition.recs[!is.na(partition.recs[,2]) & 
    !duplicated(partition.recs[,2]),]

以下是部分分区的推荐结果:
| 分区 | 推荐用户 |
| — | — |
| 0 | NA |
| 2 | cshirky |
| 3 | jeremyscahill |
| 4 | nealrichter |
| 5 | jasonmorton |
| 6 | dangerroom |
| 7 | brendan642 |
| 8 | adrianholovaty |

这些推荐结果与Drew的兴趣相匹配,且更能体现用户在不同社区的兴趣偏好。

二、支持向量机(SVM)模型

2.1 决策边界与简单分类算法的局限性

在分类问题中,决策边界起着关键作用。简单的分类算法,如逻辑回归,只能处理线性决策边界的问题。例如,对于一个数据集中Class 0的点分布在周边,Class 1的点集中在中心的情况,逻辑回归就无法发现这种非线性的决策边界。

2.2 逻辑回归的表现

我们使用 glm 函数进行逻辑回归:

df <- read.csv('data/df.csv')
logit.fit <- glm(Label ~ X + Y,
                 family = binomial(link = 'logit'),
                 data = df)
logit.predictions <- ifelse(predict(logit.fit) > 0, 1, 0)
mean(with(df, logit.predictions == Label))

结果显示,逻辑回归只能正确预测约52%的数据,这与直接预测所有数据点都属于Class 0的准确率相同,说明逻辑回归模型在这种非线性决策边界问题上完全无用。

2.3 支持向量机(SVM)的引入

SVM可以使用多种不同的核函数来找到非线性决策边界。我们使用 e1071 包中的 svm 函数:

library('e1071')
svm.fit <- svm(Label ~ X + Y, data = df)
svm.predictions <- ifelse(predict(svm.fit) > 0, 1, 0)
mean(with(df, svm.predictions == Label))

结果表明,SVM的准确率达到了72.04%,明显优于逻辑回归。

2.4 SVM的核函数

SVM的 kernel 参数可以设置为四种值:线性(linear)、多项式(polynomial)、径向(radial)和S形(sigmoid)。我们通过以下代码测试不同核函数的效果:

df <- df[, c('X', 'Y', 'Label')]
linear.svm.fit <- svm(Label ~ X + Y, data = df, kernel = 'linear')
with(df, mean(Label == ifelse(predict(linear.svm.fit) > 0, 1, 0)))
polynomial.svm.fit <- svm(Label ~ X + Y, data = df, kernel = 'polynomial')
with(df, mean(Label == ifelse(predict(polynomial.svm.fit) > 0, 1, 0)))
radial.svm.fit <- svm(Label ~ X + Y, data = df, kernel = 'radial')
with(df, mean(Label == ifelse(predict(radial.svm.fit) > 0, 1, 0)))
sigmoid.svm.fit <- svm(Label ~ X + Y, data = df, kernel = 'sigmoid')
with(df, mean(Label == ifelse(predict(sigmoid.svm.fit) > 0, 1, 0)))
df <- cbind(df,
            data.frame(LinearSVM = ifelse(predict(linear.svm.fit) > 0, 1, 0),
                       PolynomialSVM = ifelse(predict(polynomial.svm.fit) > 0, 1, 0),
                       RadialSVM = ifelse(predict(radial.svm.fit) > 0, 1, 0),
                       SigmoidSVM = ifelse(predict(sigmoid.svm.fit) > 0, 1, 0)))
predictions <- melt(df, id.vars = c('X', 'Y'))
ggplot(predictions, aes(x = X, y = Y, color = factor(value))) +
  geom_point() +
  facet_grid(variable ~ .)

结果显示,线性和多项式核函数的效果与逻辑回归相似,径向核函数能给出接近真实决策边界的结果,而S形核函数则产生非常复杂和奇怪的决策边界。

2.5 SVM的超参数调整

2.5.1 多项式核函数的 degree 超参数
polynomial.degree3.svm.fit <- svm(Label ~ X + Y,
                                  data = df,
                                  kernel = 'polynomial',
                                  degree = 3)
with(df, mean(Label != ifelse(predict(polynomial.degree3.svm.fit) > 0, 1, 0)))
polynomial.degree5.svm.fit <- svm(Label ~ X + Y,
                                  data = df,
                                  kernel = 'polynomial',
                                  degree = 5)
with(df, mean(Label != ifelse(predict(polynomial.degree5.svm.fit) > 0, 1, 0)))
polynomial.degree10.svm.fit <- svm(Label ~ X + Y,
                                   data = df,
                                   kernel = 'polynomial',
                                   degree = 10)
with(df, mean(Label != ifelse(predict(polynomial.degree10.svm.fit) > 0, 1, 0)))
polynomial.degree12.svm.fit <- svm(Label ~ X + Y,
                                   data = df,
                                   kernel = 'polynomial',
                                   degree = 12)
with(df, mean(Label != ifelse(predict(polynomial.degree12.svm.fit) > 0, 1, 0)))

结果表明,设置 degree 为3或5对模型预测质量没有影响,而设置为10或12有一定效果,但随着 degree 增加,模型拟合速度变慢,且会出现过拟合问题。因此,在应用多项式核函数的SVM时,应使用交叉验证来设置 degree 超参数。

2.5.2 所有核函数的 cost 超参数
radial.cost1.svm.fit <- svm(Label ~ X + Y,
                            data = df,
                            kernel = 'radial',
                            cost = 1)
with(df, mean(Label == ifelse(predict(radial.cost1.svm.fit) > 0, 1, 0)))
radial.cost2.svm.fit <- svm(Label ~ X + Y,
                            data = df,
                            kernel = 'radial',
                            cost = 2)
with(df, mean(Label == ifelse(predict(radial.cost2.svm.fit) > 0, 1, 0)))
radial.cost3.svm.fit <- svm(Label ~ X + Y,
                            data = df,
                            kernel = 'radial',
                            cost = 3)
with(df, mean(Label == ifelse(predict(radial.cost3.svm.fit) > 0, 1, 0)))
radial.cost4.svm.fit <- svm(Label ~ X + Y,
                            data = df,
                            kernel = 'radial',
                            cost = 4)
with(df, mean(Label == ifelse(predict(radial.cost4.svm.fit) > 0, 1, 0)))

增加 cost 参数会使模型拟合效果逐渐变差,因为 cost 是一个正则化超参数,增加它会使模型对训练数据的拟合变松。所以应通过交叉验证找到最适合测试数据的 cost 值。

2.5.3 S形核函数的 gamma 超参数
sigmoid.gamma1.svm.fit <- svm(Label ~ X + Y,
                              data = df,
                              kernel = 'sigmoid',
                              gamma = 1)
with(df, mean(Label == ifelse(predict(sigmoid.gamma1.svm.fit) > 0, 1, 0)))
sigmoid.gamma2.svm.fit <- svm(Label ~ X + Y,
                              data = df,
                              kernel = 'sigmoid',
                              gamma = 2)
with(df, mean(Label == ifelse(predict(sigmoid.gamma2.svm.fit) > 0, 1, 0)))
sigmoid.gamma3.svm.fit <- svm(Label ~ X + Y,
                              data = df,
                              kernel = 'sigmoid',
                              gamma = 3)
with(df, mean(Label == ifelse(predict(sigmoid.gamma3.svm.fit) > 0, 1, 0)))
sigmoid.gamma4.svm.fit <- svm(Label ~ X + Y,
                              data = df,
                              kernel = 'sigmoid',
                              gamma = 4)
with(df, mean(Label == ifelse(predict(sigmoid.gamma4.svm.fit) > 0, 1, 0)))

每次增加 gamma ,模型的预测效果都会略有提升,通过图形可以看到S形核函数的决策边界会随着 gamma 值的变化而改变。建议尝试更多的 gamma 值来增强对其作用的理解。

综上所述,无论是Twitter好友推荐引擎还是支持向量机模型,都有其独特的应用场景和优化方法。在实际应用中,我们需要根据具体问题选择合适的方法,并通过调整参数来优化模型性能。

三、模型对比与综合应用

3.1 不同模型性能对比

我们已经看到了逻辑回归和支持向量机(SVM)在处理非线性决策边界问题上的不同表现。逻辑回归由于只能找到线性决策边界,在处理非线性问题时效果不佳,仅能达到约52%的准确率。而SVM通过使用不同的核函数和调整超参数,能够找到更合适的非线性决策边界,例如使用径向核函数时准确率可达72.04%。

为了更直观地对比不同模型和不同SVM核函数的性能,我们可以总结如下表格:
| 模型/核函数 | 准确率 | 特点 |
| — | — | — |
| 逻辑回归 | 52% | 只能处理线性决策边界,在非线性问题上表现差 |
| SVM - 线性核 | 与逻辑回归相近 | 效果类似逻辑回归,适用于线性可分问题 |
| SVM - 多项式核 | 受 degree 影响 | 调整 degree 可能改善效果,但易过拟合 |
| SVM - 径向核 | 72.04% | 能较好地拟合非线性决策边界 |
| SVM - S形核 | 较复杂 | 决策边界复杂,需调整 gamma 优化 |

3.2 模型选择的考虑因素

在实际应用中,选择合适的模型需要考虑多个因素,其决策流程如下:

graph LR
    A[数据特征] --> B{线性可分?}
    B -- 是 --> C[逻辑回归或SVM线性核]
    B -- 否 --> D{数据规模}
    D -- 小 --> E[SVM多项式核或径向核]
    D -- 大 --> F[SVM径向核或其他高效算法]
    E --> G[调整超参数]
    F --> G
    G --> H[评估模型性能]
    H --> I{性能满意?}
    I -- 是 --> J[使用模型]
    I -- 否 --> K[尝试其他模型或调整参数]
  • 数据特征 :首先要判断数据是否线性可分。如果数据是线性可分的,那么逻辑回归或SVM的线性核函数就可以满足需求;如果数据是非线性的,则需要考虑其他核函数。
  • 数据规模 :数据规模也是一个重要因素。对于小规模数据,SVM的多项式核或径向核函数可能更合适;对于大规模数据,径向核函数可能更高效,但也可以考虑其他更适合大规模数据处理的算法。
  • 超参数调整 :选择好模型和核函数后,需要对超参数进行调整,以达到最佳性能。例如,对于多项式核函数,需要调整 degree ;对于所有核函数,需要调整 cost ;对于S形核函数,需要调整 gamma
  • 模型评估 :在调整超参数后,需要对模型进行评估,判断其性能是否满意。如果不满意,则需要尝试其他模型或继续调整参数。

3.3 模型的综合应用

在实际场景中,我们可能会遇到更复杂的问题,需要综合运用多种模型和方法。例如,在Twitter好友推荐系统中,我们可以结合用户的社交网络关系和推文内容来进行推荐。具体步骤如下:
1. 基于社交网络关系推荐 :使用前面介绍的基于“社会平衡理论”的方法,找到朋友的朋友作为推荐候选人。
2. 基于推文内容推荐 :运用文本挖掘技术,分析用户的推文内容,找到与用户兴趣相似的人。
3. 综合推荐 :将两种推荐结果进行综合,例如取交集或加权平均,得到最终的推荐列表。

以下是一个简单的综合推荐的示例代码:

# 假设 friends_recommendation 是基于社交网络关系的推荐列表
# content_recommendation 是基于推文内容的推荐列表

# 取交集
combined_recommendation <- intersect(friends_recommendation, content_recommendation)

# 或者加权平均(这里简单假设权重相同)
weighted_recommendation <- c(friends_recommendation, content_recommendation)
weighted_recommendation <- unique(weighted_recommendation)

3.4 持续优化与改进

无论是模型选择还是推荐系统,都不是一次性的工作,需要持续优化和改进。以下是一些建议:
- 数据更新 :随着时间的推移,数据会发生变化,因此需要定期更新数据,以保证模型和推荐系统的准确性。
- 模型监控 :对模型的性能进行实时监控,及时发现性能下降的情况,并采取相应的措施进行调整。
- 用户反馈 :收集用户的反馈意见,了解用户对推荐结果的满意度,根据用户反馈来改进推荐算法。

四、总结与展望

4.1 总结

本文介绍了Twitter好友推荐引擎和支持向量机(SVM)模型的构建、应用和优化方法。在Twitter好友推荐方面,我们基于“社会平衡理论”,通过分析用户的社交网络关系,找到了一种有效的推荐方法,并通过结合社区结构进一步优化了推荐结果。在SVM模型方面,我们了解了其在处理非线性决策边界问题上的优势,以及不同核函数和超参数的作用和调整方法。同时,我们还对比了不同模型的性能,提出了模型选择的考虑因素和综合应用的方法。

4.2 展望

随着数据科学和机器学习的不断发展,我们可以预见未来在这些领域会有更多的创新和应用。例如,在推荐系统方面,可以结合深度学习技术,更好地理解用户的兴趣和行为;在模型选择方面,可以使用自动化的模型选择和超参数调整方法,提高模型的性能和效率。此外,随着数据隐私和安全问题的日益突出,如何在保护用户隐私的前提下进行有效的数据挖掘和模型构建,也是未来需要研究的重要方向。

总之,无论是推荐系统还是机器学习模型,都需要不断地学习和实践,结合实际问题进行创新和优化,才能更好地满足用户的需求。希望本文能够为读者在这些领域的学习和实践提供一些有益的参考。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值