2015年3月24日星期二

机器学习,实用案例解析 by Drew Conway

相关源码:https://github.com/johnmyleswhite/ML_for_Hackers

画各个州的统计图
ggplot2 的 facet_wrap

直方图的显示效果跟宽度有关,可以换成密度曲线 
ggplot(heights.weights, aes(x = Height)) + geom_density() 

按Gender着色的密度图(合并在一张图里)
ggplot(heights.weights, aes(x = Height, fill = Gender)) + geom_density()

按Gender区分,单独画密度图
ggplot(heights.weights, aes(x = Weight, fill = Gender)) + geom_density() +
facet_grid(Gender ~ .)

散点图,同时加平滑曲线
ggplot(heights.weights, aes(x = Height, y = Weight)) + geom_point() + geom_smooth()

散点用Gender区分着色
ggplot(heights.weights, aes(x = Height, y = Weight, color = Gender)) + geom_point()

用一个数据列去预测另一个数据列,且要预测的是数值,那么就称为
回归。若要预测的是标签,就称为分类

根据身高Height、体重Weight 预测性别Gender,散点图显示分类的超平面(决策边界)。

用多个决策边界(可能非直线)进行分类。

chap 3 写了一个传统的贝叶斯垃圾邮件过滤器,prior的参数调节先验概率

chap 4 设计了几个邮件特征,根据特征取值,加上权重矩阵,计算评分。按评分排序。

chap 5
回归在二维拟合的是直线,三维拟合的是平面,三维以上拟合的是超平面。
具备可分/可加性、单调/线性 的特征时,可用线性回归。

拟合
fitted.regression <- lm(Weight ~ Height, data = heights.weights)

获取拟合的参数,第一列是截距
intercept <- coef(fitted.regression)[1]
slope <- coef(fitted.regression)[2]
# predicted.weight <- intercept + slope * observed.height

模型预测结果
predict(fitted.regression)
残差
residuals(fitted.regression)

RMSE均方误差
x <- 1:10
y <- x ^ 2
fitted.regression <- lm( y ~ x )
errors <- residuals(fitted.regression)
squared.errors <- errors ^ 2
mse <- mean(squared.errors)
rmse <- sqrt(mse)

R^2 方法用于比较预测模型的rmse,与仅采用均值预测rmse相比
r2 <-  1 - (model.rmse / mean.rmse)

对数拟合
ggplot(top.1000.sites, aes(x=log(PageViews), y=log(UniqueVisitors))) +
geom_point()+
geom_smooth(method='lm', se = FALSE)

拟合的直线
lm.fit <- lm(log(PageViews) ~ log(UniqueVisitors), data= top.1000.sites)

多变量回归
lm.fit <- lm(log(PageViews) ~ HasAdvertising + log(UniqueVisitors) + InEnglish, data= top.1000.sites)

查看UniqueVisitors对PageViews的解释能力
lm.fit <- lm(log(PageViews) ~ log(UniqueVisitors), data= top.1000.sites)
summary(lm.fit)$r.squared

两个变量的相关性
cor(x,y)
coef(lm(scale(y) ~ scale(x)))
事实上x和y的相关性 就是 关联两者的线性回归模型的x系数

chap 6
广义加性模型(GAM)拟合
geom_smooth(se = FALSE)

通过非线性函数将原始输入做映射,再将映射结果做为线性回归的输入
例如拟合 y = x^2 ,
直接用 x 做为线性回归的输入,效果就会比 x^2 做为线性回归的输入要差

通过对输入进行转换,将非线性问题转换成线性问题的思路,也是kernel trick(核方法)的本质所在。

多项式回归的拟合是比较灵活的。但是也可能拟合数据的噪声,而非拟合数据模型。

df <- transform(df, X2 = X^2)
df <- transform(df, X3 = X^3)
lm( Y <- X + X2 + X3, data = df )

奇异点问题:新增的高次方列数据,与之前的列数据太相关,以至于lm函数不能正常拟合。
奇异常解决方案:poly(X, degree=14) 生成x的高阶正交多项式,例如,不是直接生成 X+ X^2 + ... + X^14 , 而是生成一系列相互正交的多项式
lm( Y ~ poly(X, degree = 14), data = df)

复杂度的一个定义:模型中特征的权重越大,该模型越复杂
基于此提出L1/L2正则化(norm)的复杂度定义
lm.fit <- lm(y ~ x)
l2.model.complexity <- sum(coef(lm.fit) ^ 2)
l1.model.complexity <- sum(abs(coef(lm.fit)))

glmnet函数生成多个正则模型,其中lambda标识了模型复杂度,是一个回归的超参数
什么样的lambda在测试数据上效果最好,需要实际测试
注意,这不一定代表它在未来数据上效果也最好

逻辑回归,本质上是一种回归。它预测的其实是一个样本属于两个类别之中某一个的概率值。除了输出介于0~1以外,逻辑回归本质上和线性回归是一致的。

regularized.fit <- glmnet( x, y, family = 'binomial' )
family参数假定误差服从二项分布(二值分类),逻辑回归。默认则是假定误差服从高斯分布,线性回归。
例如用ifelse处理预测结果,变换为二值结果:
glm.fit <- glmnet(training.x, training.y, family = 'binomial')
predicted.y <- ifelse(predict(glm.fit, test.x, s = lambda) > 0, 1, 0)
error.rate <- mean(predicted.y != test.y)

文本逻辑回归
输入:DocumentTermMatrix形式,每个行是每个Document,每列是该列的词是否出现在该行的Document中的1/0标识。
输出:Document排名。

chap 7  优化
利用optim函数做优化
岭回归把回归系数本身当做误差项的一部分,这促使回归系数变小

chap 8 PCA
假设共有25支股票,每天一行,每个股票做为一列。要基于这25列信息,生成 一个指标,称为股市指数。
PCA的思路是创建一个25列的新数据集,根据每一列包含原始数据信息的多少排序。排第一的新列称为第一主成分。当数据集中的每一列都强相关时,PCA特别有效。
pca <- princomp(date.stock.matrix[,2:ncol(date.stock.matrix)])

看第一主成分的密度图
principal.component <- pca$loadings[,1]
loadings <- as.numeric(principal.component)
ggplot(data.frame(Loading = loadings),
              aes(x = Loading, fill = 1)) +
geom_density() +
opts(legend.position = 'none')

根据第一主成分预测
market.index <- predict(pca)[,1]

ICA,独立成分分析

chap 9  相似性
ex.matrix 的行为用户,列为用户对某商品的评价(1/0/-1)
ex.mult <- ex.matrix %*% t(ex.matrix)  每个cell为用户i与用户j评分的相同程度
ex.dist <- dist(ex.mult)  每个cell为用户i的所有评分与用户j的所有评分之间的欧氏距离

用mds可视化ex.dist
ex.mds <- cmdscale(ex.dist) 
plot(ex.mds, type='n')
另一个例子是用美国参议院的记名投票记录产生距离度量,然后使用MDS在二维空间中将参议员聚类

chap 10 推荐系统
k近邻:看与某节点最近的k个点都是啥类型。对非线性数据效果较好。
item-based : 为用户推荐与他喜欢的物品相似的物品,例如,用户比物品多
user-based:为用户推荐与他喜好相似的用户喜欢的物品,例如,物品比用户多
用KNN预测安装包也是一样思路,首先根据
    用户,安装包1,安装包2, ...
用列的协方差计算包的相似度,再通过自定义的转换公式弄成距离
计算KNN之后,提取出与"安装量多的包"距离较近的"其他包"做为安装推荐

chap 11 社交图谱
facebook 是互为好友,一个巨大的无向图
twitter 则是关注关系,一个巨大的有向图
用twitter的数据,选一个用户,分析该用户关注的对象,并将其分组。先抽出度邻居节点,再计算邻居节点之间的最短路径,然后根据hclust聚类。
可以基于twitter发言的话题喜好推荐用户
可以基于好友的共同好友推荐用户

chap 12 模型比较
用svm预测,可以指定核函数算法、以及该算法的超参数
linear.svm.fit <- svm( Label ~ X + Y, data = df, kernel = 'linear')
polynomial.degree3.svm.fit <- svm( Label ~ X + Y, data = df, kernel = 'polynomial', degree=3)
radial.cost1.svm.fit <- svm( Label ~ X + Y, data = df, kernel = 'radial', cost=1)
sigmoid.gamma1.svm.fit <- svm( Label ~ X + Y, data = df, kernel = 'sigmoid', gamma=1)
解决一个问题的最优模型取决于问题数据的内在结构
没有所谓通用的《最优》算法,《最优》取决于具体的问题

没有评论:

发表评论