【问题标题】:How to know what r is doing behind the scene如何知道 r 在幕后做什么
【发布时间】:2013-10-12 02:41:24
【问题描述】:

作为一个新的 R 用户,我很好奇当我们输入一个函数时 R 在做什么。例如,我在类包中使用 knn 函数。我需要做的就是输入 knn 并通过训练和测试数据集进行定义。然后我得到的是我的测试数据的预测类。但是,我很好奇是否有办法查看 knn 中的实际方程/公式。我浏览了一些 knn 参考资料,但仍然对 R 到底在做什么感到好奇!有没有可能找到这样的信息?

非常感谢任何帮助!!!

【问题讨论】:

  • 只需在终端输入函数名称,在这种情况下为knn,不带括号或参数。函数定义将在屏幕上返回。
  • 键入 ?getAnywhere 以查看帮助页面,了解一个非常有用的功能。

标签: r


【解决方案1】:

在您的编辑器(例如,RStudio)中,只需输入函数名称并执行该行。这显示了函数的源代码,即类型

knn

在 RStudio 中,您也可以单击该功能并按 F2。将打开一个包含函数源代码的新选项卡。

你也可以使用

debug(knn)
knn(your function arguments)

并使用调试器单步执行该函数。 完成后使用

undebug(knn)

【讨论】:

    【解决方案2】:

    嗯,您可以做的第一件事就是简单地输入函数的名称,在许多情况下,它会在此处为您提供源代码。例如:

    > knn
    function (train, test, cl, k = 1, l = 0, prob = FALSE, use.all = TRUE) 
    {
        train <- as.matrix(train)
        if (is.null(dim(test))) 
            dim(test) <- c(1, length(test))
        test <- as.matrix(test)
        if (any(is.na(train)) || any(is.na(test)) || any(is.na(cl))) 
            stop("no missing values are allowed")
        p <- ncol(train)
        ntr <- nrow(train)
        if (length(cl) != ntr) 
            stop("'train' and 'class' have different lengths")
        if (ntr < k) {
            warning(gettextf("k = %d exceeds number %d of patterns", 
                k, ntr), domain = NA)
            k <- ntr
        }
        if (k < 1) 
            stop(gettextf("k = %d must be at least 1", k), domain = NA)
        nte <- nrow(test)
        if (ncol(test) != p) 
            stop("dims of 'test' and 'train' differ")
        clf <- as.factor(cl)
        nc <- max(unclass(clf))
        Z <- .C(VR_knn, as.integer(k), as.integer(l), as.integer(ntr), 
            as.integer(nte), as.integer(p), as.double(train), as.integer(unclass(clf)), 
            as.double(test), res = integer(nte), pr = double(nte), 
            integer(nc + 1), as.integer(nc), as.integer(FALSE), as.integer(use.all))
        res <- factor(Z$res, levels = seq_along(levels(clf)), labels = levels(clf))
        if (prob) 
            attr(res, "prob") <- Z$pr
        res
    }
    <bytecode: 0x393c650>
    <environment: namespace:class>
    > 
    

    在这种情况下,您可以看到真正的工作是通过对 VR_knn 的外部调用完成的。如果你想深入挖掘,可以去http://cran.r-project.org/web/packages/class/index.html,下载这个包的源码。如果你下载并解压源代码,你会找到一个名为“src”的文件夹,其中包含 C 代码,你可以浏览它,找到该函数的源代码:

    void
    VR_knn(Sint *kin, Sint *lin, Sint *pntr, Sint *pnte, Sint *p,
           double *train, Sint *class, double *test, Sint *res, double *pr,
           Sint *votes, Sint *nc, Sint *cv, Sint *use_all)
    {
        int   i, index, j, k, k1, kinit = *kin, kn, l = *lin, mm, npat, ntie,
              ntr = *pntr, nte = *pnte, extras;
        int   pos[MAX_TIES], nclass[MAX_TIES];
        int   j1, j2, needed, t;
        double dist, tmp, nndist[MAX_TIES];
    
        RANDIN;
    /*
        Use a 'fence' in the (k+1)st position to avoid special cases.
        Simple insertion sort will suffice since k will be small.
     */
    
        for (npat = 0; npat < nte; npat++) {
        kn = kinit;
        for (k = 0; k < kn; k++)
            nndist[k] = 0.99 * DOUBLE_XMAX;
        for (j = 0; j < ntr; j++) {
            if ((*cv > 0) && (j == npat))
            continue;
            dist = 0.0;
            for (k = 0; k < *p; k++) {
            tmp = test[npat + k * nte] - train[j + k * ntr];
            dist += tmp * tmp;
            }
    /* Use 'fuzz' since distance computed could depend on order of coordinates */
            if (dist <= nndist[kinit - 1] * (1 + EPS))
            for (k = 0; k <= kn; k++)
                if (dist < nndist[k]) {
                for (k1 = kn; k1 > k; k1--) {
                    nndist[k1] = nndist[k1 - 1];
                    pos[k1] = pos[k1 - 1];
                }
                nndist[k] = dist;
                pos[k] = j;
    /* Keep an extra distance if the largest current one ties with current kth */
                if (nndist[kn] <= nndist[kinit - 1])
                    if (++kn == MAX_TIES - 1)
                    error("too many ties in knn");
                break;
                }
            nndist[kn] = 0.99 * DOUBLE_XMAX;
        }
    
        for (j = 0; j <= *nc; j++)
            votes[j] = 0;
        if (*use_all) {
            for (j = 0; j < kinit; j++)
            votes[class[pos[j]]]++;
            extras = 0;
            for (j = kinit; j < kn; j++) {
            if (nndist[j] > nndist[kinit - 1] * (1 + EPS))
                break;
            extras++;
            votes[class[pos[j]]]++;
            }
        } else { /* break ties at random */
            extras = 0;
            for (j = 0; j < kinit; j++) {
            if (nndist[j] >= nndist[kinit - 1] * (1 - EPS))
                break;
            votes[class[pos[j]]]++;
            }
            j1 = j;
            if (j1 == kinit - 1) { /* no ties for largest */
            votes[class[pos[j1]]]++;
            } else {
    /* Use reservoir sampling to choose amongst the tied distances */
            j1 = j;
            needed = kinit - j1;
            for (j = 0; j < needed; j++)
                nclass[j] = class[pos[j1 + j]];
            t = needed;
            for (j = j1 + needed; j < kn; j++) {
                if (nndist[j] > nndist[kinit - 1] * (1 + EPS))
                break;
                if (++t * UNIF < needed) {
                j2 = j1 + (int) (UNIF * needed);
                nclass[j2] = class[pos[j]];
                }
            }
            for (j = 0; j < needed; j++)
                votes[nclass[j]]++;
            }
        }
    
    /* Use reservoir sampling to choose amongst the tied votes */
        ntie = 1;
        if (l > 0)
            mm = l - 1 + extras;
        else
            mm = 0;
        index = 0;
        for (i = 1; i <= *nc; i++)
            if (votes[i] > mm) {
            ntie = 1;
            index = i;
            mm = votes[i];
            } else if (votes[i] == mm && votes[i] >= l) {
            if (++ntie * UNIF < 1.0)
                index = i;
            }
        res[npat] = index;
        pr[npat] = (double) mm / (kinit + extras);
        }
        RANDOUT;
    }
    

    【讨论】:

      【解决方案3】:

      October 2006 R News(后来演变为 The R Journal 的时事通讯)中的帮助台文章展示了如何访问涵盖您可能需要使用的许多不同情况的 R 函数源,只需键入函数名,查找命名空间,查找编译代码的源文件。

      【讨论】:

        猜你喜欢
        • 2018-08-13
        • 2014-04-09
        • 1970-01-01
        • 2016-07-04
        • 1970-01-01
        • 1970-01-01
        • 2011-07-12
        • 2020-05-21
        • 2019-05-21
        相关资源
        最近更新 更多