<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/">

	<title>Xavablog</title>
	<id>tag:xavier.robin.info,2010-05-28:/en/feed</id>
	<link rel="self" href="https://xavier.robin.info/en/feed" />
	<link rel="alternate" href="https://xavier.robin.info/en/blog"/><!--http://xavier.robin.name/comments for all comments http://xavier.robin.name/comments/path for comments on a specific post, http://xavier.robin.name/tag/(tag) for posts with 'tag'-->
	<updated>2026-10-06T16:38:07.901558000+02:00</updated>
	<sy:updatePeriod>daily</sy:updatePeriod>
	<sy:updateFrequency>2</sy:updateFrequency>
	<link rel="license" type="application/rdf+xml" href="http://creativecommons.org/licenses/by-sa/3.0/rdf" />

	<icon>https://xavier.robin.info/en/img/favicon.ico</icon>

	<author>
		<name>Xavier Robin</name>
		<uri>https://xavier.robin.info/en/contact</uri>
	</author>
	

	<entry xml:lang="en" xml:base="https://xavier.robin.info/en/">
		<title type="html">Breaking changes for ordered predictors in upcoming pROC 1.20.0</title>
		
			<category term="pROC" label="pROC" scheme="https://xavier.robin.info/en/tag/pROC" />
		
		<link href="https://xavier.robin.info/en/blog/2026/10/06/breaking-changes-for-ordered-predictors-in-upcoming-proc-1.20.0"/>
		<id>tag:xavier.robin.info,2026-10-06:/blog/2026/10/06/breaking-changes-for-ordered-predictors-in-upcoming-proc-1.20.0</id>
		<published>2026-10-06T14:26:48+02:00</published>
		<updated>2026-10-06T14:26:48+02:00</updated>
		<content type="html">&lt;p&gt;pROC has always accepted &lt;code&gt;ordered&lt;/code&gt; factors as predictors (for example &lt;code&gt;aSAH$wfns&lt;/code&gt;,
the WFNS neurological grade in the &lt;code&gt;aSAH&lt;/code&gt; dataset, with levels &lt;code&gt;1&lt;/code&gt; to &lt;code&gt;5&lt;/code&gt;).
Internally it simply called &lt;code&gt;as.numeric()&lt;/code&gt; on them and computed thresholds as the midpoints
between consecutive numeric codes (&lt;code&gt;1.5&lt;/code&gt;, &lt;code&gt;2.5&lt;/code&gt;, and so on).&lt;/p&gt;

&lt;p&gt;That&#39;s reasonable when the levels happen to be the numbers &lt;code&gt;1:n&lt;/code&gt;, but it is
not appropriate for an ordered factor whose levels are textual, for example &lt;code&gt;&quot;very low&quot;&lt;/code&gt;,
&lt;code&gt;&quot;low&quot;&lt;/code&gt;, &lt;code&gt;&quot;medium&quot;&lt;/code&gt;, &lt;code&gt;&quot;high&quot;&lt;/code&gt;, &lt;code&gt;&quot;very high&quot;&lt;/code&gt;. The thresholds
were still &lt;code&gt;-Inf, 1.5, 2.5, 3.5, 4.5, Inf&lt;/code&gt;, numbers that do not correspond to anything in
the data and are meaningless to show. This was reported as
&lt;a href=&quot;https://github.com/xrobin/pROC/issues/63&quot;&gt;issue #63&lt;/a&gt;, and a fix for it was just merged into
the &lt;code&gt;develop&lt;/code&gt; branch.&lt;/p&gt;

&lt;p&gt;In practice, this could potentially break some of your code. Before it reaches CRAN, I&#39;d like testers
who use ordered predictors to try the &lt;code&gt;develop&lt;/code&gt; version on their own data and tell me if
anything looks wrong.&lt;/p&gt;

&lt;h2&gt;What changes&lt;/h2&gt;

&lt;p&gt;On &lt;code&gt;develop&lt;/code&gt;, thresholds of an ordered ROC curve are now the predictor&#39;s own levels, plus
one infinite sentinel for the all-positive or all-negative cut-off. &lt;strong&gt;Sensitivities, specificities
and AUC are exactly the same as before&lt;/strong&gt;, only the threshold labels change, from numeric
midpoints to the levels you actually gave it:&lt;/p&gt;

&lt;pre&gt;library(pROC)
data(aSAH)

wfns.txt &amp;lt;- aSAH$wfns
levels(wfns.txt) &amp;lt;- c(&quot;very low&quot;, &quot;low&quot;, &quot;medium&quot;, &quot;high&quot;, &quot;very high&quot;)

r &amp;lt;- roc(aSAH$outcome, wfns.txt, quiet = TRUE)
r$thresholds
# very low, low, medium, high, very high, Inf
# Levels: very low &amp;lt; low &amp;lt; medium &amp;lt; high &amp;lt; very high &amp;lt; Inf

coords(r, &quot;medium&quot;)
#   threshold specificity sensitivity
# 1    medium   0.7916667   0.6585365&lt;/pre&gt;

&lt;p&gt;This is a &lt;strong&gt;breaking change&lt;/strong&gt; for any code that reads &lt;code&gt;roc$thresholds&lt;/code&gt; as numbers,
or passes a numeric cut-off into &lt;code&gt;coords()&lt;/code&gt;, &lt;code&gt;ci.thresholds()&lt;/code&gt;, &lt;code&gt;ci.coords()&lt;/code&gt;,
or &lt;code&gt;plot.roc(print.thres = ...)&lt;/code&gt; on an ordered ROC curve. Numeric predictors are entirely
unaffected by this change. Where you used to pass a midpoint, pass the level label instead:&lt;/p&gt;

&lt;pre&gt;# Incorrect (pROC &amp;lt;= 1.19.1 converted wfns to 1:5, thresholds were midpoints):
coords(roc(aSAH$outcome, aSAH$wfns), 2.5)

# Correct: pass the level label
coords(roc(aSAH$outcome, aSAH$wfns, quiet = TRUE), &quot;3&quot;)&lt;/pre&gt;

&lt;p&gt;The mapping from old midpoints to new labels is straightforward (for &lt;code&gt;direction = &quot;&amp;lt;&quot;&lt;/code&gt;,
the default): the old &lt;code&gt;-Inf&lt;/code&gt; becomes the lowest level, the old midpoint &lt;code&gt;k + 0.5&lt;/code&gt;
becomes the level in position &lt;code&gt;k + 1&lt;/code&gt;, and the old &lt;code&gt;Inf&lt;/code&gt; becomes the level literally
named &lt;code&gt;&quot;Inf&quot;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;As a side effect of the same fix, &lt;code&gt;ci.coords(..., x = &quot;best&quot;, best.policy = &quot;omit&quot;)&lt;/code&gt; now
correctly &lt;em&gt;drops&lt;/em&gt; a bootstrap replicate that has several equally-good &quot;best&quot; points, instead of
silently keeping the first one.&lt;/p&gt;

&lt;h2&gt;How to test it&lt;/h2&gt;

&lt;p&gt;This is &lt;strong&gt;not released yet&lt;/strong&gt;: it is only on the &lt;code&gt;develop&lt;/code&gt; branch, ahead of the
next CRAN release, planned for early 2027. If you use ordered predictors with &lt;code&gt;roc()&lt;/code&gt;, please
install the development version and run your own code against it:&lt;/p&gt;

&lt;pre&gt;if (! requireNamespace(&quot;devtools&quot;)) install.packages(&quot;devtools&quot;)
devtools::install_github(&quot;xrobin/pROC@develop&quot;)&lt;/pre&gt;

&lt;h2&gt;Recommendations&lt;/h2&gt;

&lt;p&gt;If you have scripts or packages that build ROC curves from ordered predictors, please run them against
the &lt;code&gt;develop&lt;/code&gt; version and check the following:&lt;/p&gt;

&lt;ul&gt;
	&lt;li&gt;Any place you hard-code a numeric threshold for an ordered predictor (in &lt;code&gt;coords()&lt;/code&gt;,
		&lt;code&gt;ci.thresholds()&lt;/code&gt;, &lt;code&gt;ci.coords()&lt;/code&gt;, or &lt;code&gt;print.thres&lt;/code&gt;) will need to
		switch to the level label.&lt;/li&gt;
	&lt;li&gt;&lt;code&gt;roc()&lt;/code&gt; now requires &lt;code&gt;cases&lt;/code&gt; and &lt;code&gt;controls&lt;/code&gt; built from ordered
		vectors to have &lt;strong&gt;identical&lt;/strong&gt; levels; it errors instead of silently coercing when they
		differ (for example after an unbalanced &lt;code&gt;droplevels()&lt;/code&gt;).&lt;/li&gt;
	&lt;li&gt;Smoothing an ordered ROC curve now only supports &lt;code&gt;method = &quot;binormal&quot;&lt;/code&gt;; other smoothing
		methods error instead of silently falling back to a numeric conversion.&lt;/li&gt;
	&lt;li&gt;AUC, DeLong and bootstrap CIs, &lt;code&gt;roc.test()&lt;/code&gt;, &lt;code&gt;cov()&lt;/code&gt;/&lt;code&gt;var()&lt;/code&gt;, and
		&lt;code&gt;power.roc.test()&lt;/code&gt; all still match what you got before. Only the thresholds
		changed, not the statistics.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If anything looks off, please comment on &lt;a href=&quot;https://github.com/xrobin/pROC/issues/63&quot;&gt;issue #63&lt;/a&gt;
or open a new issue on &lt;a href=&quot;https://github.com/xrobin/pROC/issues&quot;&gt;GitHub&lt;/a&gt; before this reaches CRAN.
Thanks in advance for testing!&lt;/p&gt;
</content>
		</entry>

	<entry xml:lang="en" xml:base="https://xavier.robin.info/en/">
		<title type="html">pROC 1.19.1</title>
		
			<category term="pROC" label="pROC" scheme="https://xavier.robin.info/en/tag/pROC" />
		
		<link href="https://xavier.robin.info/en/blog/2026/08/27/proc-1.19.1"/>
		<id>tag:xavier.robin.info,2026-08-27:/blog/2026/08/27/proc-1.19.1</id>
		<published>2026-08-27T13:10:29+02:00</published>
		<updated>2026-08-27T13:10:29+02:00</updated>
		<content type="html">&lt;p&gt;pROC 1.19.1 is a minor maintenance release. The only user-facing change is the introduction of a &lt;a href=&quot;https://cran.r-project.org/web/packages/pROC/vignettes/FAQ.html&quot;&gt;FAQ vignette&lt;/a&gt; which supersedes the old wiki.&lt;/p&gt;

&lt;p&gt;Here is the full changelog:&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;Added a FAQ vignette&lt;/li&gt;
    &lt;li&gt;Removed unused &lt;code&gt;tcltk&lt;/code&gt; from Suggests&lt;/li&gt;
    &lt;li&gt;Tests now skip if Suggest&#39;ed packages are missing&lt;/li&gt;
    &lt;li&gt;Fix CRAN checks NOTE about &lt;code&gt;structure()&lt;/code&gt; special names (&lt;code&gt;.Names&lt;/code&gt;, &lt;code&gt;.Dim&lt;/code&gt;, &lt;code&gt;.Dimnames&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;
</content>
		</entry>

	<entry xml:lang="en" xml:base="https://xavier.robin.info/en/">
		<title type="html">pROC 1.19.0</title>
		
			<category term="pROC" label="pROC" scheme="https://xavier.robin.info/en/tag/pROC" />
		
		<link href="https://xavier.robin.info/en/blog/2025/07/30/proc-1.19.0"/>
		<id>tag:xavier.robin.info,2025-07-30:/blog/2025/07/30/proc-1.19.0</id>
		<published>2025-07-30T18:56:51+02:00</published>
		<updated>2025-07-31T12:32:11+02:00</updated>
		<content type="html">&lt;p&gt;pROC version 1.19.0 was just released and will be available on CRAN very soon.&lt;/p&gt;

&lt;p&gt;Besides minor changes and fixes in the &lt;code&gt;coords&lt;/code&gt; and &lt;code&gt;ci.coords&lt;/code&gt; functions, 
  the main updates in this version focus on the core of the package, aiming to make it more modern, efficient, and easier
  to maintain. Several features that were difficult to maintain have been deprecated.&lt;/p&gt;
&lt;ul&gt;

  &lt;li&gt;The dependency on the retired &lt;a href=&quot;http://had.co.nz/plyr/&quot;&gt;plyr&lt;/a&gt; package has been removed (thanks to Michael Chirico for his contributions). 
    Unfortunately, as a side effect, progress bars and parallel processing have been removed. 
    Trying to set the &lt;code&gt;progress&lt;/code&gt; and &lt;code&gt;parallel&lt;/code&gt; arguments will now trigger a warning, and the arguments will be ignored.&lt;/li&gt;

  &lt;li&gt;As a followup from the changes to the output of the &lt;code&gt;coords&lt;/code&gt; function in version 1.16.0, the
    &lt;code&gt;transpose&lt;/code&gt;, &lt;code&gt;as.list&lt;/code&gt;, &lt;code&gt;as.matrix&lt;/code&gt; and &lt;code&gt;drop&lt;/code&gt; arguments have been
    deprecated.
    The &lt;code&gt;coords&lt;/code&gt; function currently has multiple exit points, depending on arguments and inputs, and can return
    retults in mutliple formats. This makes it difficult to use and to maintain.
    Going forward, &lt;code&gt;coords&lt;/code&gt; will only retrun data in a single, tidy &lt;code&gt;data.frame&lt;/code&gt; format, compatible following modern R
    coding practices.
    For compatibility reasons, deprecated arguments are still available, but setting them to non default
    values will trigger warnings. They will be removed in a future release.
    If your code still uses these arguments, please update it accordingly.&lt;/li&gt;

  &lt;li&gt;Finally, following years of performance improvements, an in an effort to simplify the codebase, all ROC computation
    algorithms other than 2 have been removed as they no longer provided meaningful performance advantages. The &lt;code&gt;algorithm&lt;/code&gt;
    argument to &lt;code&gt;roc&lt;/code&gt; has been deprecated. Setting it to a non-default value has no effect and triggers a warning.
    The &lt;code&gt;fun.sesp&lt;/code&gt; value of &lt;code&gt;roc&lt;/code&gt; objects is also deprecated. Calling it triggers a warning.
    Both will be removed in a future release of pROC.&lt;/li&gt;
&lt;/ul&gt;
	
&lt;p&gt;Here is the full changelog:&lt;/p&gt;

&lt;ul&gt;
	&lt;li&gt;&lt;code&gt;ci.coords&lt;/code&gt; can now take the same &lt;code&gt;input&lt;/code&gt; values as &lt;code&gt;coords&lt;/code&gt; (&lt;a href=&quot;https://github.com/xrobin/pROC/issues/90&quot;&gt;issue #90&lt;/a&gt;)&lt;/li&gt;
	&lt;li&gt;&lt;code&gt;ci.coords&lt;/code&gt; can be &lt;code&gt;plot&lt;/code&gt;ted&lt;/li&gt;
	&lt;li&gt;Added &quot;lr_pos&quot; and &quot;lr_neg&quot; to &lt;code&gt;coords&lt;/code&gt; (&lt;a href=&quot;https://github.com/xrobin/pROC/issues/102&quot;&gt;issue #102&lt;/a&gt;)&lt;/li&gt;
	&lt;li&gt;&lt;code&gt;coords&lt;/code&gt; with partial.auc now interpolates bounds when needed&lt;/li&gt;
	&lt;li&gt;Added &lt;code&gt;ignore.partial.auc&lt;/code&gt; argument to &lt;code&gt;coords&lt;/code&gt;&lt;/li&gt;
	&lt;li&gt;Deprecated &lt;code&gt;transpose&lt;/code&gt;, &lt;code&gt;as.list&lt;/code&gt;, &lt;code&gt;as.matrix&lt;/code&gt; and &lt;code&gt;drop&lt;/code&gt; in &lt;code&gt;coords&lt;/code&gt;&lt;/li&gt;
	&lt;li&gt;Deprecated the &lt;code&gt;algorithm&lt;/code&gt; argument to &lt;code&gt;roc&lt;/code&gt; and &lt;code&gt;fun.sesp&lt;/code&gt; value&lt;/li&gt;
	&lt;li&gt;Deprecated the &lt;code&gt;progress&lt;/code&gt; and &lt;code&gt;parallel&lt;/code&gt; argument for bootstrap operations.&lt;/li&gt;
	&lt;li&gt;Removed dependencies on &lt;a href=&quot;https://cran.r-project.org/web/packages/doParallel/index.html&quot;&gt;doParallel&lt;/a&gt; and retired package &lt;a href=&quot;http://had.co.nz/plyr/&quot;&gt;plyr&lt;/a&gt; (thanks to Michael Chirico, &lt;a href=&quot;https://github.com/xrobin/pROC/pull/134&quot;&gt;pr #134&lt;/a&gt;, &lt;a href=&quot;https://github.com/xrobin/pROC/pull/135&quot;&gt;#135&lt;/a&gt;, &lt;a href=&quot;https://github.com/xrobin/pROC/pull/136&quot;&gt;#136&lt;/a&gt;, &lt;a href=&quot;https://github.com/xrobin/pROC/pull/137&quot;&gt;#137&lt;/a&gt;, &lt;a href=&quot;https://github.com/xrobin/pROC/pull/138&quot;&gt;#138&lt;/a&gt;, &lt;a href=&quot;https://github.com/xrobin/pROC/pull/139&quot;&gt;#139&lt;/a&gt; and &lt;a href=&quot;https://github.com/xrobin/pROC/pull/140&quot;&gt;#140&lt;/a&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can update your installation by simply typing:&lt;/p&gt;

&lt;pre&gt;install.packages(&quot;pROC&quot;)&lt;/pre&gt;

&lt;hr&gt;

&lt;p&gt;Update: pROC 1.19.0 was rejected from CRAN. A patch revision 1.19.0.1 was created to workaround an issue with a reverse dependency but provides no meaningful change:&lt;/p&gt;

&lt;ul&gt;
	&lt;li&gt;Move &lt;code&gt;fun.sesp&lt;/code&gt; definition to work around &lt;a href=&quot;https://github.com/LudvigOlsen/cvms/pull/44&quot;&gt;LudvigOlsen/cvms#44&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;</content>
		</entry>

	<entry xml:lang="en" xml:base="https://xavier.robin.info/en/">
		<title type="html">pROC 1.18.5</title>
		
			<category term="pROC" label="pROC" scheme="https://xavier.robin.info/en/tag/pROC" />
		
		<link href="https://xavier.robin.info/en/blog/2023/11/02/proc-1.18.5"/>
		<id>tag:xavier.robin.info,2023-11-02:/blog/2023/11/02/proc-1.18.5</id>
		<published>2023-11-02T17:01:20+01:00</published>
		<updated>2023-11-02T17:01:20+01:00</updated>
		<content type="html">&lt;p&gt;pROC 1.18.5 is now available on CRAN. It&#39;s a minor bugfix release:&lt;/p&gt;

&lt;ul&gt;
	&lt;li&gt;Fixed formula input when given as variable and combined with &lt;code&gt;with&lt;/code&gt; (&lt;a href=&quot;https://github.com/xrobin/pROC/issues/111&quot;&gt;issue #111&lt;/a&gt;)&lt;/li&gt;
	&lt;li&gt;Fixed formula containing variables with spaces (&lt;a href=&quot;https://github.com/xrobin/pROC/issues/120&quot;&gt;issue #120&lt;/a&gt;)&lt;/li&gt;
	&lt;li&gt;Fixed broken grouping when &lt;code&gt;colour&lt;/code&gt; argument was given in &lt;code&gt;ggroc&lt;/code&gt; (&lt;a href=&quot;https://github.com/xrobin/pROC/issues/121&quot;&gt;issue #121&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can update your installation by simply typing:&lt;/p&gt;

&lt;pre&gt;install.packages(&quot;pROC&quot;)&lt;/pre&gt;</content>
		</entry>

	<entry xml:lang="en" xml:base="https://xavier.robin.info/en/">
		<title type="html">Deep Learning of MNIST handwritten digits</title>
		
			<category term="programming" label="Programming" scheme="https://xavier.robin.info/en/tag/programming" />
		
		<link href="https://xavier.robin.info/en/blog/2022/06/11/deep-learning-of-mnist-handwritten-digits"/>
		<id>tag:xavier.robin.info,2022-06-11:/blog/2022/06/11/deep-learning-of-mnist-handwritten-digits</id>
		<published>2022-06-11T16:39:25+02:00</published>
		<updated>2022-06-11T16:39:25+02:00</updated>
		<content type="html">&lt;p&gt;In this document I am going create a video showing the training of the inner-most layer of Deep Belief Network (DBN) using the MNIST dataset of handwritten digits. I will use our &lt;code&gt;DeepLearning&lt;/code&gt; R package that implements flexible DBN architectures with an object-oriented interface.&lt;/p&gt;

&lt;h2&gt;MNIST&lt;/h2&gt;
&lt;p&gt;The MNIST dataset is a database of handwritten digits with 60,000 training images and 10,000 testing images. &lt;a href=&quot;https://en.wikipedia.org/wiki/MNIST_database&quot; title=&quot;Wikipedia: MNIST database&quot;&gt;You can learn everything about it on Wikipedia&lt;/a&gt;. In short, it is the go-to dataset to train and test handwritten digit recognition machine learning algorithms.&lt;/p&gt;


&lt;p&gt;I made an R package for easy access, named &lt;code&gt;mnist&lt;/code&gt;. The easiest way to install it is with &lt;code&gt;devtools&lt;/code&gt;. If you don&#39;t have it already, let&#39;s first install &lt;code&gt;devtools&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;
if (!require(&quot;devtools&quot;)) {install.packages(&quot;devtools&quot;)}
&lt;/pre&gt;

&lt;p&gt;Now we can install &lt;code&gt;mnist&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;
devtools::install_github(&quot;xrobin/mnist&quot;)
&lt;/pre&gt;

&lt;h2&gt;PCA&lt;/h2&gt;
&lt;p&gt;In order to see what the dataset looks like, let&#39;s use PCA to reduce it to two dimensions.&lt;/p&gt;

&lt;pre&gt;
pca &amp;lt;- prcomp(mnist$train$x)
plot.mnist(
	prediction = predict(pca, mnist$test$x),
	reconstruction = tcrossprod(
		predict(pca, mnist$test$x)[,1:2], pca$rotation[,1:2]),
	highlight.digits = c(72, 3, 83, 91, 6688, 7860, 92, 1, 180, 13))
&lt;/pre&gt;

&lt;p&gt;&lt;img src=&quot;/files/blog/2022/06/11/pca.png&quot; style=&quot;max-width: 100%&quot; alt=&quot;PCA Scatterplot&quot;&gt;&lt;/p&gt;
	
&lt;p&gt;Let&#39;s take a minute to describe this plot.
The central scatterplot shows first two components of the PCA of all digits in the test set.
On the left hand side, I picked 10 representative digits from the test set to highlight, which are shown as larger circles in the central scatterplot.
On the left are the &quot;reconstructed digits&quot;, which were reconstructed from the two first dimensions of the PCA. While we can see some digit-like structures, it is basically impossible to recognize them.
We can see some separation of the digits in the 2D space as well, but it is pretty weak and some pairs cannot be distinguished at all (like 4 and 9).
Of course the reconstructions would look much better had we kept all PCA dimensions, but so much for dimensionality reduction.&lt;/p&gt;


&lt;h2&gt;Deep Learning&lt;/h2&gt;
&lt;p&gt;Now let&#39;s see if we can do better with Deep Learning. We&#39;ll use a classical Deep Belief Network (DBN), based on Restricted Boltzmann Machines (RBM) similar to what Hinton described back in 2006 (Hinton &amp;amp; Salakhutdinov, 2006). The training happens in two steps: a pre-training step with contrastive divergence stochastic gradient descent brings the network to a reasonable starting point for a more conventional conjugate gradient optimization (hereafter referred to as fine-tuning).&lt;/p&gt;

&lt;p&gt;I implemented this algorithm with a few modifications in an R package which is available on GitHub. The core of the processing is done in C++ with &lt;a href=&quot;https://cran.r-project.org/web/packages/RcppEigen/index.html&quot;&gt;RcppEigen&lt;/a&gt; (Bates &amp;amp; Eddelbuettel, 2013) for higher speed. Using &lt;code&gt;devtools&lt;/code&gt; again:&lt;/p&gt;
&lt;pre&gt;
devtools::install_github(&quot;xrobin/DeepLearning&quot;)
&lt;/pre&gt;

&lt;p&gt;We will use this code to train a 5 layers deep network, that reduces the digits to an abstract, 2D representation. By looking at this last layer throughout the training process we can start to understand how the network learns to recognize digits. Let&#39;s start by loading the required packages and the MNIST dataset, and create the DBN.&lt;/p&gt;

&lt;pre&gt;library(DeepLearning)
library(mnist)
data(mnist)

dbn &amp;lt;- DeepBeliefNet(Layers(c(784, 1000, 500, 250, 2),
	input = &quot;continuous&quot;, output = &quot;gaussian&quot;),
	initialize = &quot;0&quot;)
&lt;/pre&gt;
&lt;p&gt;We just created the 5-layers DBN, with continuous, 784 nodes input (the digit image pixels), and a 2 nodes, gaussian output. It is initialized with 0, but we could have left out the &lt;code&gt;initialize&lt;/code&gt; to start from a random initilization (Bengio &lt;i&gt;et al.&lt;/i&gt;, 2007). Before we go, let&#39;s define a few useful variables:&lt;/p&gt;

&lt;pre&gt;
output.folder &amp;lt;- &quot;video&quot; # Where to save the output
maxiters.pretrain &amp;lt;- 1e6  # Number of pre-training iterations
maxiters.train &amp;lt;- 10000 # Number of fine-tuning iterations
run.training &amp;lt;- run.images &amp;lt;- TRUE # Turn any of these off 
# Which digits to highlight and reconstruct
highlight.digits = c(72, 3, 83, 91, 6688, 7860, 92, 1, 180, 13)
&lt;/pre&gt;

&lt;p&gt;We&#39;ll also need the following function to show the elapsed time:&lt;/p&gt;
&lt;pre&gt;
format.timediff &amp;lt;- function(start.time) {
    diff = as.numeric(difftime(Sys.time(), start.time, units=&quot;mins&quot;))
    hr &amp;lt;- diff%/%60
    min &amp;lt;- floor(diff - hr * 60)
    sec &amp;lt;- round(diff%%1 * 60,digits=2)
    return(paste(hr,min,sec,sep=&#39;:&#39;))
}
&lt;/pre&gt;

&lt;h2&gt;Pre-training&lt;/h2&gt;
&lt;p&gt;Initially, the network is a stack of RBMs that we need to &lt;em&gt;pre-train&lt;/em&gt; one by one. Hinton &amp;amp; Salakhutdinov (2006) showed that this step is critical to train deep networks. We will use 1000000 iterations (&lt;code&gt;maxiters.pretrain&lt;/code&gt;) of contrastive divergence, which takes a couple of days on a modern CPU. Let&#39;s start with the first three RBMs:&lt;/p&gt;

&lt;h3&gt;First three RBMs&lt;/h3&gt;
&lt;pre&gt;
if (run.training) {
	sprintf.fmt.iter &amp;lt;- sprintf(&quot;%%0%dd&quot;, nchar(sprintf(&quot;%d&quot;, maxiters.pretrain)))
	
	mnist.data.layer &amp;lt;- mnist
	for (i in 1:3) {
&lt;/pre&gt;
&lt;p&gt;We define a &lt;code&gt;diag&lt;/code&gt; function that will simply print where we are in the training. Because this function will be called a million times (&lt;code&gt;maxiters.pretrain&lt;/code&gt;), we can use &lt;code&gt;rate = &quot;accelerate&quot;&lt;/code&gt; to slow down the printing over time and save a few CPU cycles.&lt;/p&gt;
&lt;pre&gt;
		diag &amp;lt;- list(rate = &quot;accelerate&quot;, data = NULL, f = function(rbm, batch, data, iter, batchsize, maxiters, layer) {
			print(sprintf(&quot;%s[%s/%s] in %s&quot;, layer, iter, maxiters, format.timediff(start.time)))
		})
&lt;/pre&gt;
&lt;p&gt;We can get the current RBM, and we will work on it directly. Let&#39;s save it for good measure, as well as the current time for the progress function:&lt;/p&gt;
&lt;pre&gt;
		rbm &amp;lt;- dbn[[i]]
		save(rbm, file = file.path(output.folder, sprintf(&quot;rbm-%s-%s.RData&quot;, i, &quot;initial&quot;)))
		start.time &amp;lt;- Sys.time()
&lt;/pre&gt;
&lt;p&gt;Now we can start the actual pre-training:&lt;/p&gt;
&lt;pre&gt;
		rbm &amp;lt;- pretrain(rbm, mnist.data.layer$train$x,
			penalization = &quot;l2&quot;, lambda=0.0002, momentum = c(0.5, 0.9),
			epsilon=c(.1, .1, .1, .001)[i], batchsize = 100, maxiters=maxiters.pretrain,
			continue.function = continue.function.always, diag = diag)
&lt;/pre&gt;
&lt;p&gt;This can take some time, especially for the first layers which are larger. Once it is done, we predict the data through this RBM for the next layer and save the results:&lt;/p&gt;
&lt;pre&gt;
		mnist.data.layer$train$x &amp;lt;- predict(rbm, mnist.data.layer$train$x)
		mnist.data.layer$test$x &amp;lt;- predict(rbm, mnist.data.layer$test$x)
		save(rbm, file = file.path(output.folder, sprintf(&quot;rbm-%s-%s.RData&quot;, i, &quot;final&quot;)))
		dbn[[i]] &amp;lt;- rbm
	}
&lt;/pre&gt;

&lt;h3&gt;Last RBM&lt;/h3&gt;
&lt;p&gt;This is very similar to the previous three, but note that we save the RBM within the &lt;code&gt;diag&lt;/code&gt; function. We could generate the plot directly, but it is easier to do it later once we have some idea about the final axis we will need. Please note the &lt;code&gt;rate = &quot;accelerate&quot;&lt;/code&gt; here. You probably don&#39;t want to save a million RBM objects on your hard drive, both for speed and space reasons.&lt;/p&gt;

&lt;pre&gt;
	rbm &amp;lt;- dbn[[4]]
	print(head(rbm$b))
	diag &amp;lt;- list(rate = &quot;accelerate&quot;, data = NULL, f = function(rbm, batch, data, iter, batchsize, maxiters, layer) {
		save(rbm, file = file.path(output.folder, sprintf(&quot;rbm-4-%s.RData&quot;, sprintf(sprintf.fmt.iter, iter))))
		print(sprintf(&quot;%s[%s/%s] in %s&quot;, layer, iter, maxiters, format.timediff(start.time)))
	})
	save(rbm, file = file.path(output.folder, sprintf(&quot;rbm-%s-%s.RData&quot;, 4, &quot;initial&quot;)))
	start.time &amp;lt;- Sys.time()
	rbm &amp;lt;- pretrain(rbm, mnist.data.layer$train$x,  penalization = &quot;l2&quot;, lambda=0.0002,
		epsilon=.001, batchsize = 100, maxiters=maxiters.pretrain,
		continue.function = continue.function.always, diag = diag)
	save(rbm, file = file.path(output.folder, sprintf(&quot;rbm-4-%s.RData&quot;, &quot;final&quot;)))
	dbn[[4]] &amp;lt;- rbm
&lt;/pre&gt;

&lt;iframe src=&quot;https://www.youtube.com/embed/3EapaWpDqGQ&quot; title=&quot;YouTube video player&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture&quot; allowfullscreen style=&quot;	width: 100%; aspect-ratio: 16/9; border: none;&quot;&gt;&lt;/iframe&gt;

&lt;p&gt;If we were not querying the last layer, we could have pre-trained the entire network at once with the following call:&lt;/p&gt;

&lt;pre&gt;
	dbn &amp;lt;- pretrain(dbn, mnist.data.layer$train$x, 
		penalization = &quot;l2&quot;, lambda=0.0002, momentum = c(0.5, 0.9),
		epsilon=c(.1, .1, .1, .001), batchsize = 100, 
		maxiters=maxiters.pretrain,
		continue.function = continue.function.always)
&lt;/pre&gt;	 

&lt;h3&gt;Pre-training parameters&lt;/h3&gt;
&lt;p&gt;Pre-training RBMs is quite sensitive to the use of proper parameters.
 With improper parameters, the network can quickly go crazy and start to generate infinite values. If that happens to you, you should try to tune one of the following parameters:
 
&lt;ul&gt;
 &lt;li&gt;&lt;code&gt;penalization&lt;/code&gt;: this is the penalty of introducing or increasing the value of a weight. We used L2 regularization, but &lt;code&gt;&quot;l1&quot;&lt;/code&gt; is available if a sparser weight matrix is needed.&lt;/li&gt;
 &lt;li&gt;&lt;code&gt;lambda&lt;/code&gt;: the regularization rate. In our experience 0.0002 works fine with the MNIST and other datasets of similar sizes such as cellular imaging data. Too small or large values will result in over- or under-fitted networks, respectively.&lt;/li&gt;
 &lt;li&gt;&lt;code&gt;momentum&lt;/code&gt;: helps avoiding oscillatory behaviors, where the network oscillate between iterations. Allowed values can range from 0 (no momentum) to 1 (full momentum = no training). Here we used an increasing gradient of momentum which starts at 0.5 and increases linearly to 0.9, in order to stabilize the final network without compromising early training steps.&lt;/li&gt;
 &lt;li&gt;&lt;code&gt;epsilon&lt;/code&gt;: the learning rate. Typically, 0.1 works well with binary and continuous output layers, and must be decreased to around 0.001 for gaussian outputs. Too large values will drive the network to generate infinities, while too small ones will slow down the training.&lt;/li&gt;
 &lt;li&gt;&lt;code&gt;batchsize&lt;/code&gt;: larger batch sizes will result in smoother but slower training. Small batch sizes will make the training &quot;jumpy&quot;, which can be compensated by lower learning rates (epsilon) or increased momentum.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Fine-tuning&lt;/h2&gt;
&lt;p&gt;This is where the real training happens. We use conjugate gradients to find the optimal solution. Again, the &lt;code&gt;diag&lt;/code&gt; function saves the DBN. This time we use &lt;code&gt;rate = &quot;each&quot;&lt;/code&gt; to save every step of the training. First we have way fewer steps, but also the training itself happen at a much more stable speed than in the pre-training, where things slow down dramatically.
&lt;/p&gt;

&lt;pre&gt;
	sprintf.fmt.iter &amp;lt;- sprintf(&quot;%%0%dd&quot;, nchar(sprintf(&quot;%d&quot;, maxiters.train)))
	diag &amp;lt;- list(rate = &quot;each&quot;, data = NULL, f = function(dbn, batch, data, iter, batchsize, maxiters) {
		save(dbn, file = file.path(output.folder, sprintf(&quot;dbn-finetune-%s.RData&quot;, sprintf(sprintf.fmt.iter, iter))))
		print(sprintf(&quot;[%s/%s] in %s&quot;, iter, maxiters, format.timediff(start.time)))
	})
	save(dbn, file = file.path(output.folder, sprintf(&quot;dbn-finetune-%s.RData&quot;, &quot;initial&quot;)))
	start.time &amp;lt;- Sys.time()
	dbn &amp;lt;- train(unroll(dbn), mnist$train$x, batchsize = 100, maxiters=maxiters.train,
		continue.function = continue.function.always, diag = diag)
	save(dbn, file = file.path(output.folder, sprintf(&quot;dbn-finetune-%s.RData&quot;, &quot;final&quot;)))
}
&lt;/pre&gt;

&lt;iframe src=&quot;https://www.youtube.com/embed/wSfoZ_kMMTc&quot; title=&quot;YouTube video player&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture&quot; allowfullscreen style=&quot;	width: 100%; aspect-ratio: 16/9; border: none;&quot;&gt;&lt;/iframe&gt;

&lt;p&gt;And that&#39;s it, our DBN is now fully trained!&lt;/p&gt;

&lt;h2&gt;Generating the images&lt;/h2&gt;
&lt;p&gt;Now we need to read in the saved network states again, pass the data through the network (&lt;code&gt;predict&lt;/code&gt;) and save this in HD-sized PNG file.&lt;/p&gt;

&lt;p&gt;The first three RBMs are only loaded into the DBN&lt;/p&gt;

&lt;pre&gt;
if (run.images) {
	for (i in 1:3) {
		load(file.path(output.folder, sprintf(&quot;rbm-%d-final.RData&quot;, i)))
		dbn[[i]] &amp;lt;- rbm
	}
&lt;/pre&gt;

&lt;p&gt;The last RBM is where interesting things happen.&lt;/p&gt;
&lt;pre&gt;
	for (file in list.files(output.folder, pattern = &quot;rbm-4-.+\\.RData&quot;, full.names = TRUE)) {
		print(file)
		load(file)
		dbn[[4]] &amp;lt;- rbm
		iter &amp;lt;- stringr::str_match(file, &quot;rbm-4-(.+)\\.RData&quot;)[,2]
&lt;/pre&gt;
&lt;p&gt;We now predict and reconstruct the data, and calculate the mean reconstruction error:&lt;/p&gt;
&lt;pre&gt;
		predictions &amp;lt;- predict(dbn, mnist$test$x)
		reconstructions &amp;lt;- reconstruct(dbn, mnist$test$x)
		iteration.error &amp;lt;- errorSum(dbn, mnist$test$x) / nrow(mnist$test$x)
&lt;/pre&gt;
&lt;p&gt;Now the actual plotting. Here I selected &lt;code&gt;xlim&lt;/code&gt; and &lt;code&gt;ylim&lt;/code&gt; values that worked well for my training run, but your mileage may vary.&lt;/p&gt;
&lt;pre&gt;
		png(sub(&quot;.RData&quot;, &quot;.png&quot;, file), width = 1280, height = 720) # hd output
		plot.mnist(model = dbn, x = mnist$test$x, label = mnist$test$y+1, predictions = predictions, reconstructions = reconstructions,
				   ncol = 16, highlight.digits = highlight.digits,
				   xlim = c(-12.625948, 8.329168), ylim = c(-10.50657, 13.12654))
		par(family=&quot;mono&quot;)
		legend(&quot;bottomleft&quot;, legend = sprintf(&quot;Mean error = %.3f&quot;, iteration.error), bty=&quot;n&quot;, cex=3)
		legend(&quot;bottomright&quot;, legend = sprintf(&quot;Iteration = %s&quot;, iter), bty=&quot;n&quot;, cex=3)
		dev.off()
	}
&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;/files/blog/2022/06/11/rbm-4-final.png&quot; style=&quot;max-width: 100%&quot; alt=&quot;Scatterplot after pretraining&quot;&gt;&lt;/p&gt;

&lt;p&gt;We do the same with the fine-tuning:&lt;/p&gt;
&lt;pre&gt;
	for (file in list.files(output.folder, pattern = &quot;dbn-finetune-.+\\.RData&quot;, full.names = TRUE)) {
		print(file)
		load(file)
		iter &amp;lt;- stringr::str_match(file, &quot;dbn-finetune-(.+)\\.RData&quot;)[,2]
		predictions &amp;lt;- predict(dbn, mnist$test$x)
		reconstructions &amp;lt;- reconstruct(dbn, mnist$test$x)
		iteration.error &amp;lt;- errorSum(dbn, mnist$test$x) / nrow(mnist$test$x)
		png(sub(&quot;.RData&quot;, &quot;.png&quot;, file), width = 1280, height = 720) # hd output
		plot.mnist(model = dbn, x = mnist$test$x, label = mnist$test$y+1, predictions = predictions, reconstructions = reconstructions,
				   ncol = 16, highlight.digits = highlight.digits,
				   xlim = c(-22.81098,  27.94829), ylim = c(-17.49874,  33.34688))
		par(family=&quot;mono&quot;)
		legend(&quot;bottomleft&quot;, legend = sprintf(&quot;Mean error = %.3f&quot;, iteration.error), bty=&quot;n&quot;, cex=3)
		legend(&quot;bottomright&quot;, legend = sprintf(&quot;Iteration = %s&quot;, iter), bty=&quot;n&quot;, cex=3)
		dev.off()
	}
}
&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;/files/blog/2022/06/11/dbn-finetune-final.png&quot; style=&quot;max-width: 100%&quot; alt=&quot;Scatterplot after fine-tuning&quot;&gt;&lt;/p&gt;

&lt;h2&gt;The video&lt;/h2&gt;

&lt;p&gt;I simply used &lt;a href=&quot;https://ffmpeg.org/&quot;&gt;ffmpeg&lt;/a&gt; to convert the PNG files to a video:&lt;/p&gt;
&lt;pre&gt;
cd video
ffmpeg -pattern_type glob -i &quot;rbm-4-*.png&quot; -b:v 10000000 -y ../rbm-4.mp4
ffmpeg -pattern_type glob -i &quot;dbn-finetune-*.png&quot; -b:v 10000000 -y ../dbn-finetune.mp4
&lt;/pre&gt;

&lt;p&gt;And that&#39;s it! Notice how the pre-training only brings the network to a state similar to that of a PCA, and the fine-tuning actually does the separation, and how it really makes the reconstructions accurate.&lt;/p&gt;

&lt;h2&gt;Application&lt;/h2&gt;
&lt;p&gt;We used this code to analyze changes in cell morphology upon drug resistance in cancer. With a 27-dimension space, we could describe all of the observed cell morphologies and predict whether a cell was resistant to ErbB-family drugs with an accuracy of 74%. The paper is available in Open Access in Cell Reports, DOI &lt;a href=&quot;https://doi.org/10.1016/j.celrep.2020.108657&quot; title=&quot;Deep neural networks identify signaling mechanisms of ErbB-family drug resistance from a continuous cell morphology space&quot;&gt;10.1016/j.celrep.2020.108657&lt;/a&gt;.

&lt;h2&gt;Concluding remarks&lt;/h2&gt;
&lt;p&gt;In this document I described how to build and train a DBN with the &lt;code&gt;DeepLearning&lt;/code&gt; package. I also showed how to query the internal layer, and use the generative properties to follow the training of the network on handwritten digits.&lt;/p&gt;
&lt;p&gt;DBNs have the advantage over Convolutional Networks (CN) that they are fully generative, at least during the pre-training. They are therefore easier to query and interpret as we have demonstrated here. 
 However keep in mind that CNs have demonstrated higher accuracies on computer vision tasks, such as the MNIST dataset.&lt;/p&gt;
&lt;p&gt;Additional algorithmic details are available in the &lt;code&gt;doc&lt;/code&gt; folder of the DeepLearning package.&lt;/p&gt;


&lt;h2&gt;References&lt;/h2&gt;
&lt;dl&gt;
	&lt;dt&gt;Our paper, 2021&lt;/dt&gt;
	&lt;dd&gt;Longden J., Robin X., Engel M., &lt;i&gt;et al.&lt;/i&gt;
 &lt;a href=&quot;https://doi.org/10.1016/j.celrep.2020.108657&quot;&gt;Deep neural networks identify signaling mechanisms of ErbB-family drug resistance from a continuous cell morphology space&lt;/a&gt;. &lt;i&gt;Cell Reports&lt;/i&gt;, 2021;34(3):108657.&lt;/dd&gt;

	&lt;dt&gt;Bates &amp;amp; Eddelbuettel, 2013&lt;/dt&gt;
	&lt;dd&gt;Bates D, Eddelbuettel D. &lt;a href=&quot;http://www.jstatsoft.org/v52/i05/&quot;&gt;Fast and Elegant Numerical Linear Algebra Using the RcppEigen Package&lt;/a&gt;. &lt;i&gt;Journal of Statistical Software&lt;/i&gt;, 2013;52(5):1&amp;ndash;24.&lt;/dd&gt;

	&lt;dt&gt;Bengio &lt;i&gt;et al.&lt;/i&gt;, 2007&lt;/dt&gt;
	&lt;dd&gt;Bengio Y, Lamblin P, Popovici D, Larochelle H. &lt;a href=&quot;https://papers.nips.cc/paper/3048-greedy-layer-wise-training-of-deep-networks.pdf&quot;&gt;Greedy layer-wise training of deep networks&lt;/a&gt;. &lt;i&gt;Advances in neural information processing systems&lt;/i&gt;. 2007;19:153&amp;ndash;60.&lt;/dd&gt;

	&lt;dt&gt;Hinton &amp;amp; Salakhutdinov, 2006&lt;/dt&gt;
	&lt;dd&gt;Hinton GE, Salakhutdinov RR. &lt;a href=&quot;http://dx.doi.org/10.1126/science.1127647&quot;&gt;Reducing the Dimensionality of Data with Neural Networks&lt;/a&gt;. &lt;i&gt;Science&lt;/i&gt;. 2006;313(5786):504&amp;ndash;7.&lt;/dd&gt;
&lt;/dl&gt;

&lt;h2&gt;Downloads&lt;/h2&gt;
&lt;ol&gt;
	&lt;li&gt;&lt;a href=&quot;/files/blog/2022/06/11/MNIST_video.tar.gz&quot;&gt;Code to generate the video&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;https://github.com/xrobin/DeepLearning&quot;&gt;DeepLearning package source code&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
</content>
		</entry>

	<entry xml:lang="en" xml:base="https://xavier.robin.info/en/">
		<title type="html">pROC 1.18.0</title>
		
			<category term="pROC" label="pROC" scheme="https://xavier.robin.info/en/tag/pROC" />
		
		<link href="https://xavier.robin.info/en/blog/2021/09/06/proc-1.18.0"/>
		<id>tag:xavier.robin.info,2021-09-06:/blog/2021/09/06/proc-1.18.0</id>
		<published>2021-09-06T18:34:01+02:00</published>
		<updated>2021-09-06T18:34:01+02:00</updated>
		<content type="html">&lt;p&gt;pROC version 1.18.0 is now available on CRAN now. Only a few changes were implemented in this release:&lt;/p&gt;

&lt;ul&gt;
	&lt;li&gt;Add &lt;abbr title=&quot;Confidence Interval&quot;&gt;CI&lt;/abbr&gt; of the estimate for &lt;code&gt;roc.test&lt;/code&gt; (DeLong, paired only for now) (code contributed by &lt;a href=&quot;https://wz-billings.rbind.io/&quot;&gt;Zane Billings&lt;/a&gt;) (&lt;a href=&quot;https://github.com/xrobin/pROC/pull/95&quot;&gt;issue #95&lt;/a&gt;).&lt;/li&gt;
	&lt;li&gt;Fix documentation and alternative hypothesis for Venkatraman test (&lt;a href=&quot;https://github.com/xrobin/pROC/issues/92&quot;&gt;issue #92&lt;/a&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can update your installation by simply typing:&lt;/p&gt;

&lt;pre&gt;install.packages(&quot;pROC&quot;)&lt;/pre&gt;</content>
		</entry>

	<entry xml:lang="en" xml:base="https://xavier.robin.info/en/">
		<title type="html">pROC 1.17.0.1</title>
		
			<category term="pROC" label="pROC" scheme="https://xavier.robin.info/en/tag/pROC" />
		
		<link href="https://xavier.robin.info/en/blog/2021/01/13/proc-1.17.0.1"/>
		<id>tag:xavier.robin.info,2021-01-13:/blog/2021/01/13/proc-1.17.0.1</id>
		<published>2021-01-13T16:19:16+01:00</published>
		<updated>2021-01-13T16:19:16+01:00</updated>
		<content type="html">&lt;p&gt;pROC version 1.17.0.1 is available on CRAN now. Besides several bug fixes and small changes, it introduces more values in &lt;code&gt;input&lt;/code&gt; of &lt;code&gt;coords&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Here is an example:&lt;/p&gt;

&lt;pre&gt;
library(pROC)
data(aSAH)
rocobj &amp;lt;- roc(aSAH$outcome, aSAH$s100b)
coords(rocobj, x = seq(0, 1, .1), input=&quot;recall&quot;, ret=&quot;precision&quot;)
#    precision
# 1        NaN
# 2  1.0000000
# 3  1.0000000
# 4  0.8601399
# 5  0.6721311
# 6  0.6307692
# 7  0.6373057
# 8  0.4803347
# 9  0.4517906
# 10 0.3997833
# 11 0.3628319
&lt;/pre&gt;

	
&lt;h2&gt;Getting the update&lt;/h2&gt;

&lt;p&gt;The update his available on CRAN now. You can update your installation by simply typing:&lt;/p&gt;

&lt;pre&gt;install.packages(&quot;pROC&quot;)&lt;/pre&gt;

&lt;p&gt;Here is the full changelog:&lt;/p&gt; 

&lt;p&gt;1.17.0.1 (2020-01-07):&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;Fix CRAN incoming checks as requested by CRAN.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;1.17.0 (2020-12-29)&lt;/p&gt;

&lt;ul&gt;
	&lt;li&gt;Accept more values in &lt;code&gt;input&lt;/code&gt; of &lt;code&gt;coords&lt;/code&gt; (&lt;a href=&quot;https://github.com/xrobin/pROC/issues/67&quot;&gt;issue #67&lt;/a&gt;).&lt;/li&gt;
	&lt;li&gt;Accept &lt;code&gt;kappa&lt;/code&gt; for the &lt;code&gt;power.roc.test&lt;/code&gt; of two ROC curves (&lt;a href=&quot;https://github.com/xrobin/pROC/issues/82&quot;&gt;issue #82&lt;/a&gt;).&lt;/li&gt;
	&lt;li&gt;The &lt;code&gt;input&lt;/code&gt; argument to &lt;code&gt;coords&lt;/code&gt; for &lt;code&gt;smooth.roc&lt;/code&gt; curves no longer has a default.&lt;/li&gt;
	&lt;li&gt;The &lt;code&gt;x&lt;/code&gt; argument to &lt;code&gt;coords&lt;/code&gt; for &lt;code&gt;smooth.roc&lt;/code&gt; can now be set to &lt;code&gt;all&lt;/code&gt; (also the default).&lt;/li&gt;
	&lt;li&gt;Fix bootstrap &lt;code&gt;roc.test&lt;/code&gt; and &lt;code&gt;cov&lt;/code&gt; with &lt;code&gt;smooth.roc&lt;/code&gt; curves.&lt;/li&gt;
	&lt;li&gt;The &lt;code&gt;ggroc&lt;/code&gt; function can now plot &lt;code&gt;smooth.roc&lt;/code&gt; curves (&lt;a href=&quot;https://github.com/xrobin/pROC/issues/86&quot;&gt;issue #86&lt;/a&gt;).&lt;/li&gt;
	&lt;li&gt;Remove warnings with &lt;code&gt;warnPartialMatchDollar&lt;/code&gt; option (&lt;a href=&quot;https://github.com/xrobin/pROC/issues/87&quot;&gt;issue #87&lt;/a&gt;).&lt;/li&gt;
	&lt;li&gt;Make tests depending on vdiffr conditional (&lt;a href=&quot;https://github.com/xrobin/pROC/issues/88&quot;&gt;issue #88&lt;/a&gt;).&lt;/li&gt;
&lt;/ul&gt;</content>
		</entry>

	<entry xml:lang="en" xml:base="https://xavier.robin.info/en/">
		<title type="html">pROC 1.16.1</title>
		
			<category term="pROC" label="pROC" scheme="https://xavier.robin.info/en/tag/pROC" />
		
		<link href="https://xavier.robin.info/en/blog/2020/01/14/proc-1.16.1"/>
		<id>tag:xavier.robin.info,2020-01-14:/blog/2020/01/14/proc-1.16.1</id>
		<published>2020-01-14T08:52:57+01:00</published>
		<updated>2020-01-14T08:52:57+01:00</updated>
		<content type="html">&lt;p&gt;pROC version 1.16.1 is a minor release that disables a timing-dependent test based on the microbenchmark package that can sometimes cause random failures on CRAN. This version contains no user-visible changes. Users don&#39;t need to install this update.&lt;/p&gt;
</content>
		</entry>

	<entry xml:lang="en" xml:base="https://xavier.robin.info/en/">
		<title type="html">pROC 1.16.0</title>
		
			<category term="pROC" label="pROC" scheme="https://xavier.robin.info/en/tag/pROC" />
		
		<link href="https://xavier.robin.info/en/blog/2020/01/12/proc-1.16.0"/>
		<id>tag:xavier.robin.info,2020-01-12:/blog/2020/01/12/proc-1.16.0</id>
		<published>2020-01-12T21:46:00+01:00</published>
		<updated>2020-01-12T21:46:00+01:00</updated>
		<content type="html">&lt;p&gt;pROC version 1.16.0 is available on CRAN now. Besides several bug fixes, the main change is the switch of the default value of the &lt;code&gt;transpose&lt;/code&gt; argument to the &lt;code&gt;coords&lt;/code&gt; function from &lt;code&gt;TRUE&lt;/code&gt; to &lt;code&gt;FALSE&lt;/code&gt;. As announced earlier, &lt;strong&gt;this is a backward incompatible change that will break any script that did not previously set the &lt;code&gt;transpose&lt;/code&gt; argument&lt;/strong&gt; and for now comes with a warning to make debugging easier. Scripts that set transpose explicitly are not unaffected.&lt;/p&gt;

&lt;h2&gt;New return values of &lt;code&gt;coords&lt;/code&gt; and &lt;code&gt;ci.coords&lt;/code&gt;&lt;/h2&gt;

&lt;p&gt;With &lt;code&gt;transpose = FALSE&lt;/code&gt;, the &lt;code&gt;coords&lt;/code&gt; returns a tidy &lt;code&gt;data.frame&lt;/code&gt; suitable for use in pipelines:&lt;/p&gt;

&lt;pre&gt;
data(aSAH)
rocobj &amp;lt;- roc(aSAH$outcome, aSAH$s100b)
coords(rocobj, c(0.05, 0.2, 0.5), transpose = FALSE)
#      threshold specificity sensitivity
# 0.05      0.05  0.06944444   0.9756098
# 0.2       0.20  0.80555556   0.6341463
# 0.5       0.50  0.97222222   0.2926829
&lt;/pre&gt;

&lt;p&gt;The function doesn&#39;t drop dimensions, so the result is always a &lt;code&gt;data.frame&lt;/code&gt;, even if it has only one row and/or one column.&lt;/p&gt;

&lt;p&gt;If speed is of utmost importance, you can get the results as a non-transposed matrix instead:
&lt;pre&gt;
coords(rocobj, c(0.05, 0.2, 0.5), transpose = FALSE, as.matrix = TRUE)
#      threshold specificity sensitivity
# [1,]      0.05  0.06944444   0.9756098
# [2,]      0.20  0.80555556   0.6341463
# [3,]      0.50  0.97222222   0.2926829
&lt;/pre&gt;

&lt;p&gt;In some scenarios this can be a tiny bit faster, and is used internally in &lt;code&gt;ci.coords&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Type &lt;code&gt;help(coords_transpose)&lt;/code&gt; for additional information.&lt;/p&gt;

&lt;h3&gt;&lt;code&gt;ci.coords&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;The &lt;code&gt;ci.coords&lt;/code&gt; function now returns a list-like object:&lt;/p&gt;
&lt;pre&gt;
ciobj &amp;lt;- ci.coords(rocobj, c(0.05, 0.2, 0.5))
ciobj$accuracy
#        2.5%       50%     97.5%
# 1 0.3628319 0.3982301 0.4424779
# 2 0.6637168 0.7433628 0.8141593
# 3 0.6725664 0.7256637 0.7787611
&lt;/pre&gt;

&lt;p&gt;The &lt;code&gt;print&lt;/code&gt; function prints a table with all the results, however this table is generated on the fly and not available directly.&lt;/p&gt;

&lt;pre&gt;ciobj
# 95% CI (2000 stratified bootstrap replicates):
#      threshold sensitivity.low sensitivity.median sensitivity.high
# 0.05      0.05          0.9268             0.9756           1.0000
# 0.2       0.20          0.4878             0.6341           0.7805
# 0.5       0.50          0.1707             0.2927           0.4390
#      specificity.low specificity.median specificity.high accuracy.low
# 0.05         0.01389            0.06944           0.1250       0.3628
# 0.2          0.70830            0.80560           0.8889       0.6637
# 0.5          0.93060            0.97220           1.0000       0.6726
#      accuracy.median accuracy.high
# 0.05          0.3982        0.4425
# 0.2           0.7434        0.8142
# 0.5           0.7257        0.7788
&lt;/pre&gt;

&lt;p&gt;The following code snippet can be used to obtain all the information calculated by the function:&lt;/p&gt;
&lt;pre&gt;
for (ret in attr(ciobj, &quot;ret&quot;)) {
	print(ciobj[[ret]])
}
#        2.5%       50%     97.5%
# 1 0.9268293 0.9756098 1.0000000
# 2 0.4878049 0.6341463 0.7804878
# 3 0.1707317 0.2926829 0.4390244
#         2.5%        50%     97.5%
# 1 0.01388889 0.06944444 0.1250000
# 2 0.70833333 0.80555556 0.8888889
# 3 0.93055556 0.97222222 1.0000000
#        2.5%       50%     97.5%
# 1 0.3628319 0.3982301 0.4424779
# 2 0.6637168 0.7433628 0.8141593
# 3 0.6725664 0.7256637 0.7787611
&lt;/pre&gt;
	
&lt;h2&gt;Getting the update&lt;/h2&gt;

&lt;p&gt;The update his available on CRAN now. You can update your installation by simply typing:&lt;/p&gt;

&lt;pre&gt;install.packages(&quot;pROC&quot;)&lt;/pre&gt;

&lt;p&gt;Here is the full changelog:&lt;/p&gt; 

&lt;ul&gt;
	&lt;li&gt;BACKWARD INCOMPATIBLE CHANGE: &lt;code&gt;transpose&lt;/code&gt; argument to &lt;code&gt;coords&lt;/code&gt; switched to &lt;code&gt;FALSE&lt;/code&gt; by default (&lt;a href=&quot;https://github.com/xrobin/pROC/issues/54&quot;&gt;issue #54&lt;/a&gt;).&lt;/li&gt;
	&lt;li&gt;BACKWARD INCOMPATIBLE CHANGE: &lt;code&gt;ci.coords&lt;/code&gt; return value is now of list type and easier to use.&lt;/li&gt;
	&lt;li&gt;Fix one-sided DeLong test for curves with &lt;code&gt;direction=&quot;&amp;gt;&quot;&lt;/code&gt; (&lt;a href=&quot;https://github.com/xrobin/pROC/issues/64&quot;&gt;issue #64&lt;/a&gt;).&lt;/li&gt;
	&lt;li&gt;Fix an error in &lt;code&gt;ci.coords&lt;/code&gt; due to expected &lt;code&gt;NA&lt;/code&gt; values in some coords (like &quot;precision&quot;) (&lt;a href=&quot;https://github.com/xrobin/pROC/issues/65&quot;&gt;issue #65&lt;/a&gt;).&lt;/li&gt;
	&lt;li&gt;Ordrered predictors are converted to numeric in a more robust way (&lt;a href=&quot;https://github.com/xrobin/pROC/issues/63&quot;&gt;issue #63&lt;/a&gt;).&lt;/li&gt;
	&lt;li&gt;Cleaned up &lt;code&gt;power.roc.test&lt;/code&gt; code (&lt;a href=&quot;https://github.com/xrobin/pROC/issues/50&quot;&gt;issue #50&lt;/a&gt;).&lt;/li&gt;
	&lt;li&gt;Fix pairing with &lt;code&gt;roc.formula&lt;/code&gt; and warn if &lt;code&gt;na.action&lt;/code&gt; is not set to &lt;code&gt;&quot;na.pass&quot;&lt;/code&gt; or &lt;code&gt;&quot;na.fail&quot;&lt;/code&gt; (&lt;a href=&quot;https://github.com/xrobin/pROC/issues/68&quot;&gt;issue #68&lt;/a&gt;).&lt;/li&gt;
	&lt;li&gt;Fix &lt;code&gt;ci.coords&lt;/code&gt; not working with &lt;code&gt;smooth.roc&lt;/code&gt; curves.&lt;/li&gt;
&lt;/ul&gt;</content>
		</entry>

	<entry xml:lang="en" xml:base="https://xavier.robin.info/en/">
		<title type="html">pROC 1.15.3</title>
		
			<category term="pROC" label="pROC" scheme="https://xavier.robin.info/en/tag/pROC" />
		
		<link href="https://xavier.robin.info/en/blog/2019/07/22/proc-1.15.3"/>
		<id>tag:xavier.robin.info,2019-07-22:/blog/2019/07/22/proc-1.15.3</id>
		<published>2019-07-22T09:07:57+02:00</published>
		<updated>2019-07-22T09:07:57+02:00</updated>
		<content type="html">&lt;p&gt;A new version of pROC, 1.15.3, has been released and is now available on CRAN. It is a minor bugfix release. Versions 1.15.1 and 1.15.2 were rejected from CRAN.&lt;/p&gt;


&lt;p&gt;Here is the full changelog:&lt;/p&gt; 

&lt;ul&gt;
	&lt;li&gt;Fix &lt;code&gt;-Inf&lt;/code&gt; threshold in coords for curves with &lt;code&gt;direction = &quot;&gt;&quot;&lt;/code&gt; (&lt;a href=&quot;https://github.com/xrobin/pROC/issues/60&quot;&gt;issue 60&lt;/a&gt;).&lt;/li&gt;
	&lt;li&gt;Keep list order in &lt;code&gt;ggroc&lt;/code&gt; (&lt;a href=&quot;https://github.com/xrobin/pROC/issues/58&quot;&gt;issue 58&lt;/a&gt;).&lt;/li&gt;
	&lt;li&gt;Fix erroneous error in &lt;code&gt;ci.coords&lt;/code&gt; with &lt;code&gt;ret=&quot;threshold&quot;&lt;/code&gt; (&lt;a href=&quot;https://github.com/xrobin/pROC/issues/57&quot;&gt;issue 57&lt;/a&gt;).&lt;/li&gt;
	&lt;li&gt;Restore lazy loading of the data and fix an &lt;code&gt;R CMD check&lt;/code&gt; warning &quot;Variables with usage in documentation object &#39;aSAH&#39; not in code&quot;.&lt;/li&gt;
	&lt;li&gt;Fix vdiffr unit tests with ggplot2 3.2.0 (&lt;a href=&quot;https://github.com/xrobin/pROC/issues/53&quot;&gt;issue 53&lt;/a&gt;).&lt;/li&gt;
&lt;/ul&gt;
</content>
		</entry>


</feed>
