• [读书笔记]机器学习:实用案例解析(6)


    第6章  正则化:文本回归

    线性回归的非线性扩展:广义加性模型(GAM, Generalized Additive Model)R语言中可用gam()函数实现

    多项式回归:degree值不能无限增大,否则会产生过拟合(overfitting)现象。

    过拟合:指模型拟合了部分噪声

    避免过拟合的手段:交叉验证(cross-validation)和正则化(regularization)

    模型复杂度:一个模型中特征的权重越大,这个模型越复杂

    L1正则化(L1 norm)与L2正则化(L2 norm):分别累加模型系数的绝对值和系数的平方

    set.seed(1)
    x <- seq(0, 1, by = 0.01)
    y <- sin(2 * pi * x) + rnorm(length(x), 0, 0.1)
    #L1 norm and L2 norm
    lm.fit <- lm(y ~ x)
    l2.model.complexity <- sum(coef(lm.fit) ^ 2)
    l1.model.complexity <- sum(abs(coef(lm.fit)))
    

      

    可以训练正则化的线性模型的函数:glmnet()

    x <- as.matrix(cbind(x, rev(x)))
    library(glmnet)
    glmnet(x, y)
    

      

        

    结果解释:

    Df:指明模型中的非零权重有几个(不包括截距项)

    %Dev:模型的R2值。第2行对应的是完全正则化,最后一行[55]对应的是完全没有正则化

    Lambda:超参数(hyperparameter)可以看做是一个惩罚参数,lambda很大时,表明对复杂度很在意,使模型权重趋于0,反之则会得到一个比较复杂的模型

    为了得到最优模型,要设定一个大小适中的lambda. 为了得到这个lambda,首先设定一个较大的次数,比如10,然后使用不同的lambda分别在测试集上训练模型,再看效果如何,最后通过迭代多次不同的lambda,找到这个最好的lambda

    ########################################################

    #文本回归
    #研究描述文本与销量之间的关系

    ranks <- read.csv('ML_for_Hackers/06-Regularization/data/oreilly.csv')
    library(tm)
    documents <- data.frame(Text = ranks$Long.Desc.)
    row.names(documents) <- 1:nrow(documents)
    

      

    #将原始数据集转化为一个文档词项矩阵

    #这里注意,由于tm包更新到0.6-0以后,tolower()等函数的返回有可能不是dtm的格式(之前版本默认返回相应格式)

    #因此书中模型会有一个错误

    #需要将代码修改为

    corpus <- Corpus(DataframeSource(documents))
    corpus <- tm_map(corpus, content_transformer(tolower))
    corpus <- tm_map(corpus, content_transformer(stripWhitespace))
    corpus <- tm_map(corpus, removeWords, stopwords('english'))
    dtm <- DocumentTermMatrix(corpus)
    

      

    #将文档词项矩阵转换为一个简单矩阵,将顺序值颠倒过来作为预测值(使权重未正)
    #初始化随机种子
    #对于6个lambda值,分别交叉验证50次,并作图

    x <- as.matrix(dtm)
    y <- rev(1:100)
    set.seed(1)
    performance <- data.frame()
    for(lambda in c(0.1, 0.25, 0.5, 1, 2, 5)) {
      for(i in 1:50) {
        indices <- sample(1:100, 80)
        training.x <- x[indices, ]
        training.y <- y[indices]
        test.x <- x[-indices, ]
        test.y <- y[-indices]
        glm.fit <- glmnet(training.x, training.y)
        predicted.y <- predict(glm.fit, test.x, s = lambda)
        rmse <- sqrt(mean((predicted.y - test.y) ^ 2))
        performance <- rbind(performance, data.frame(Lambda = lambda, Iteration = i, RMSE = rmse))
      }
    }
    ggplot(performance, aes(x = Lambda, y = RMSE)) + 
      stat_summary(fun.data = 'mean_cl_boot', geom = 'errorbar') + 
      stat_summary(fun.data = 'mean_cl_boot', geom = 'point')
    

      

    分析:由图可见,随着lambda越来越大,模型的表现越来越好,但是lambda增大后是趋于简化模型,即常数模型的情况,没有用到特征的信息。

    简而言之,这个文本回归模型没有发现有意义的信息,给出的预测完全是随机噪声。

    #########################################################################

      数据中也许并没有答案。有一堆数据和对答案的热切渴望,并不能确保真的能从这堆数据中提取出合理的预期答案。

    ——John Tukey

    #########################################################################

    将回归问题转化为分类问题,采用逻辑回归的办法再进行尝试

    #分类办法:用逻辑值1/0作为分类标准,是否进入前50

    #评价模型的标准用错误率评价,更多的循环次数会对错误率有更准确的估计

    #代码优化:将两个循环交换,不必为每一个lambda做多次拆分,提高运行效率

    set.seed(1)
    performance <- data.frame()
    for(i in 1:250) {
      indices <- sample(1:100, 80)
      training.x <- x[indices, ]
      training.y <- y[indices]
      test.x <- x[-indices, ]
      test.y <- y[-indices]
      for(lambda in c(0.0001, 0.001, 0.0025, 0.01, 0.025, 0.5, 0.1)) {
        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)
        performance <- rbind(performance, data.frame(Lambda = lambda, Iteration = i, ErrorRate = error.rate))
        }
    }
    ggplot(performance, aes(x = Lambda, y = ErrorRate)) + 
      stat_summary(fun.data = 'mean_cl_boot', geom = 'errorbar') + 
      stat_summary(fun.data = 'mean_cl_boot', geom = 'point') + 
      scale_x_log10()
    

      

    结果可以看到,将回归问题改成分类问题时,较小的lambda可以预测一本书能否进入销售榜前50,是有意义的。

    总结:有些情况下,手中的数据并不能解决较复杂的问题(回归问题:预测排行),但是却可以解决一些简单问题(分类问题:是否进入前50)

    参考:http://stackoverflow.com/questions/24191728/documenttermmatrix-error-on-corpus-argument

  • 相关阅读:
    总结thinkphp快捷查询getBy、getField、getFieldBy用法及场景
    javascript中的那些让人摸不着头脑的不=
    使用jquery静态资源公共库cdn及回退地址
    论strpos 的正确使用方式
    深入解析array_merge函数的用法 php
    thinkphp集成系列之rbac的升级版auth权限管理系统demo
    thinkphp集成系列之短信验证码、订单通知
    sublime安装ctags函数追踪插件
    Sublime Text3下配置SublimeLinter进行PHP代码检查
    win7启动redis报错Creating Server TCP listening socket *:6379: bind: Unknown error
  • 原文地址:https://www.cnblogs.com/gyjerry/p/5578638.html
Copyright © 2020-2023  润新知