<p dir="auto">I think there is a bug in the method predict of the class _PLS. More specifically, if I choose to scale the dataset during training (scale=True), then the method "predict" does not seem to reverse the scaling operation:</p>
<blockquote>
<p dir="auto">return Ypred + self.y_mean_</p>
</blockquote>
<p dir="auto">(line 435 of the source code available at <a href="https://github.com/scikit-learn/scikit-learn/blob/c957249/sklearn/cross_decomposition/pls_.py#L437">https://github.com/scikit-learn/scikit-learn/blob/c957249/sklearn/cross_decomposition/pls_.py#L437</a>)</p>
<p dir="auto">I believe that the we should first reverse the scaling operation in each column of Ypred (by using the corresponding component of self.y_std_) :</p>
<blockquote>
<p dir="auto">return Ypred * self.y_std_ + self.y_mean_</p>
</blockquote>
<p dir="auto">Am I missing anything here?</p>
<p dir="auto">I am trying to fit some spectral data using PLS, and am having difficulties with the module.</p>
<p dir="auto">Essentially, when I use the default value of <code class="notranslate">scale=False</code>, I get a prediction, BUT all my predictions are scaled, and I just cannot figure out how to convert back to my original data space.  The same is true for the example code.  As you see, the scaled prediction is just off.  I assumed that I should be able to revert back to the "unscaled" data using <code class="notranslate">pls_scaled.y_mean_</code> and <code class="notranslate">pls_scaled.y_std_</code>, but that doesn't seem to work for me.  Any suggestions would be highly appreciated.</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="Y = np.array([[0.1, -0.2], [0.9, 1.1], [6.2, 5.9], [11.9, 12.3]])
X = np.array([[0., 0., 1.], [1.,0.,0.], [2.,2.,2.], [2.,5.,4.]])
pls_not_scaled=PLSRegression(n_components=2, scale=False)
pls_scaled=PLSRegression(n_components=2, scale=True)
pls_not_scaled.fit(X,Y)
Out[]: PLSRegression(copy=True, max_iter=500, n_components=2, scale=False, tol=1e-06)
pls_scaled.fit(X,Y)
Out[]: PLSRegression(copy=True, max_iter=500, n_components=2, scale=True, tol=1e-06)
Out[]: PLSRegression(copy=True, max_iter=500, n_components=2, scale=False, tol=1e-06)
Y_not_scaled_pred = pls_not_scaled.predict(X)
Y_scaled_pred = pls_scaled.predict(X)

print(Y)
[[  0.1  -0.2]
 [  0.9   1.1]
 [  6.2   5.9]
 [ 11.9  12.3]]

print(Y_not_scaled_pred)
[[  0.11029323  -0.09323388]
 [  0.86825958   0.77077371]
 [  6.24049125   6.31999396]
 [ 11.88095594  12.1024662 ]]

print(Y_scaled_pred)
[[ 1.52568016  1.47577156]
 [ 2.43367318  2.3584298 ]
 [ 6.25638942  6.26638408]
 [ 8.88425724  8.99941456]]"><pre class="notranslate"><code class="notranslate">Y = np.array([[0.1, -0.2], [0.9, 1.1], [6.2, 5.9], [11.9, 12.3]])
X = np.array([[0., 0., 1.], [1.,0.,0.], [2.,2.,2.], [2.,5.,4.]])
pls_not_scaled=PLSRegression(n_components=2, scale=False)
pls_scaled=PLSRegression(n_components=2, scale=True)
pls_not_scaled.fit(X,Y)
Out[]: PLSRegression(copy=True, max_iter=500, n_components=2, scale=False, tol=1e-06)
pls_scaled.fit(X,Y)
Out[]: PLSRegression(copy=True, max_iter=500, n_components=2, scale=True, tol=1e-06)
Out[]: PLSRegression(copy=True, max_iter=500, n_components=2, scale=False, tol=1e-06)
Y_not_scaled_pred = pls_not_scaled.predict(X)
Y_scaled_pred = pls_scaled.predict(X)

print(Y)
[[  0.1  -0.2]
 [  0.9   1.1]
 [  6.2   5.9]
 [ 11.9  12.3]]

print(Y_not_scaled_pred)
[[  0.11029323  -0.09323388]
 [  0.86825958   0.77077371]
 [  6.24049125   6.31999396]
 [ 11.88095594  12.1024662 ]]

print(Y_scaled_pred)
[[ 1.52568016  1.47577156]
 [ 2.43367318  2.3584298 ]
 [ 6.25638942  6.26638408]
 [ 8.88425724  8.99941456]]
</code></pre></div>
<p dir="auto">For those with a more visual bend:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="plt.grid('on')
plt.scatter(Y[:, 0], Y_not_scaled_pred[:, 0], color='blue')
plt.scatter(Y[:, 0], Y_scaled_pred[:, 0], color='red')
plt.xlabel('Predicted')
plt.ylabel('Measured')
plt.legend(['not_scaled','scaled'],'lower right')"><pre class="notranslate"><code class="notranslate">plt.grid('on')
plt.scatter(Y[:, 0], Y_not_scaled_pred[:, 0], color='blue')
plt.scatter(Y[:, 0], Y_scaled_pred[:, 0], color='red')
plt.xlabel('Predicted')
plt.ylabel('Measured')
plt.legend(['not_scaled','scaled'],'lower right')
</code></pre></div>
<p dir="auto"><a target="_blank" rel="noopener noreferrer nofollow" href="https://cloud.githubusercontent.com/assets/13950307/11730049/a1fcfa66-9f60-11e5-960f-90fa260eef6a.png"><img src="https://cloud.githubusercontent.com/assets/13950307/11730049/a1fcfa66-9f60-11e5-960f-90fa260eef6a.png" alt="figure_1" style="max-width: 100%;"></a></p>