diff --git a/sklearn/__init__.py b/sklearn/__init__.py
index 0b18b081b8..70f8a606b4 100644
--- a/sklearn/__init__.py
+++ b/sklearn/__init__.py
@@ -143,10 +143,12 @@ else:
                'mixture', 'model_selection', 'multiclass', 'multioutput',
                'naive_bayes', 'neighbors', 'neural_network', 'pipeline',
                'preprocessing', 'random_projection', 'semi_supervised',
-               'svm', 'tree', 'discriminant_analysis',
+               'svm', 'tree', 'discriminant_analysis', 'daal4sklearn',
                # Non-modules:
                'clone']
 
+    from .daal4sklearn import dispatcher
+    dispatcher.enable()
 
 def setup_module(module):
     """Fixture for the tests to assure globally controllable seeding of RNGs"""
@@ -162,3 +164,4 @@ def setup_module(module):
     print("I: Seeding RNGs with %r" % _random_seed)
     np.random.seed(_random_seed)
     random.seed(_random_seed)
+
diff --git a/sklearn/cluster/tests/test_k_means.py b/sklearn/cluster/tests/test_k_means.py
index 7e33fabc5a..4e294d4325 100644
--- a/sklearn/cluster/tests/test_k_means.py
+++ b/sklearn/cluster/tests/test_k_means.py
@@ -5,6 +5,7 @@ import numpy as np
 from scipy import sparse as sp
 
 from sklearn.utils.testing import assert_equal
+from sklearn.utils.testing import assert_allclose
 from sklearn.utils.testing import assert_array_equal
 from sklearn.utils.testing import assert_array_almost_equal
 from sklearn.utils.testing import SkipTest
@@ -546,7 +547,7 @@ def test_k_means_non_collapsed():
     km = KMeans(init=array_init, n_clusters=3, random_state=42, n_init=1)
     km.fit(my_X)
 
-    # centers must not been collapsed
+    # centers must not have been collapsed
     assert_equal(len(np.unique(km.labels_)), 3)
 
     centers = km.cluster_centers_
@@ -803,12 +804,12 @@ def test_float_precision():
             # compare arrays with low precision since the difference between
             # 32 and 64 bit sometimes makes a difference up to the 4th decimal
             # place
-            assert_array_almost_equal(inertia[np.float32], inertia[np.float64],
-                                      decimal=4)
-            assert_array_almost_equal(X_new[np.float32], X_new[np.float64],
-                                      decimal=4)
-            assert_array_almost_equal(centers[np.float32], centers[np.float64],
-                                      decimal=4)
+            assert_allclose(inertia[np.float32], inertia[np.float64],
+                                      atol=1e-4, rtol=1e-4)
+            assert_allclose(X_new[np.float32], X_new[np.float64],
+                                      atol=1e-3, rtol=1e-4)
+            assert_allclose(centers[np.float32], centers[np.float64],
+                                      atol=1e-4, rtol=1e-4)
 
 
 def test_k_means_init_centers():
diff --git a/sklearn/daal4sklearn/__init__.py b/sklearn/daal4sklearn/__init__.py
new file mode 100644
index 0000000000..0a88ddf145
--- /dev/null
+++ b/sklearn/daal4sklearn/__init__.py
@@ -0,0 +1 @@
+__all__ = ["dispatcher", "k_means", "linear", "pairwise", "pca", "ridge", "utils"]
diff --git a/sklearn/daal4sklearn/dispatcher.py b/sklearn/daal4sklearn/dispatcher.py
new file mode 100644
index 0000000000..41aa8b8a47
--- /dev/null
+++ b/sklearn/daal4sklearn/dispatcher.py
@@ -0,0 +1,65 @@
+from .. import __version__ as sklearn_version
+
+from ..decomposition.pca import PCA
+from ..cluster.k_means_ import KMeans
+from ..metrics import pairwise
+from ..linear_model.base import LinearRegression
+from ..linear_model.ridge import Ridge
+from ..svm.classes import SVC
+
+from .k_means import fit as kmeans_fit
+from .k_means import predict as kmeans_predict
+from .pca import _fit_full as pca_fit_full
+from .pairwise import daal_pairwise_distances
+from .linear import fit as linear_fit
+from .linear import predict as linear_predict
+from .ridge import fit as ridge_fit
+from .ridge import predict as ridge_predict
+from .svm import fit as svm_fit
+from .svm import predict as svm_predict
+
+
+mapping = {'PCA_full':  [[(PCA, '_fit_full', pca_fit_full), None]],
+           'KMeans':    [[(KMeans, 'fit', kmeans_fit), None], [(KMeans, 'predict', kmeans_predict), None]],
+           'distances': [[(pairwise, 'pairwise_distances', daal_pairwise_distances), None]],
+           'linear':    [[(LinearRegression, 'fit', linear_fit), None],
+                         [(LinearRegression, 'predict', linear_predict), None]],
+           'ridge':     [[(Ridge, 'fit', ridge_fit), None],
+                         [(Ridge, 'predict', ridge_predict), None]],
+           'SVM':       [[(SVC, 'fit', svm_fit), None],
+                         [(SVC, 'predict', svm_predict), None]], }
+
+
+def do_patch(name):
+    if name in mapping:
+        for descriptor in mapping[name]:
+            which, what, replacer = descriptor[0]
+            if descriptor[1] is None:
+                descriptor[1] = getattr(which, what)
+            setattr(which, what, replacer)
+    else:
+        raise ValueError("Has no patch for: " + name)
+
+def do_unpatch(name):
+    if name in mapping:
+        for descriptor in mapping[name]:
+            which, what, replacer = descriptor[0]
+            setattr(which, what, descriptor[1])
+    else:
+        raise ValueError("Has no patch for: " + name)
+
+def enable(name=None):
+    if sklearn_version != "0.19.1":
+        raise NotImplementedError("daal4sklearn is for scikit-learn 0.19.1 only, found version {0}".format(sklearn_version))
+    if name is not None:
+        do_patch(name)
+    else:
+        for key in mapping:
+            do_patch(key)
+
+def disable(name=None):
+    if name is not None:
+        do_unpatch(name)
+    else:
+        for key in mapping:
+            do_unpatch(key)
diff --git a/sklearn/daal4sklearn/k_means.py b/sklearn/daal4sklearn/k_means.py
new file mode 100644
index 0000000000..b3efceb149
--- /dev/null
+++ b/sklearn/daal4sklearn/k_means.py
@@ -0,0 +1,202 @@
+import numpy as np
+from scipy import sparse as sp
+from ..utils import check_random_state
+from ..utils.sparsefuncs import mean_variance_axis
+from ..utils.validation import check_is_fitted
+from ..cluster.k_means_ import k_means
+from ..externals.six import string_types
+from .utils import getArrayFromNumericTable, make_csr_table, make_HomogenNumericTable
+from daal.data_management import CSRNumericTable
+from daal.data_management import HomogenNumericTable,HomogenNumericTable_Float32,HomogenNumericTable_Intc
+from daal.algorithms.kmeans import Batch_Float64LloydDense, Batch_Float64LloydCSR, init, data, inputCentroids, assignments, centroids, goalFunction, nIterations, Batch_Float32LloydDense, Batch_Float32LloydCSR
+
+def daal_k_means_dense(X, nClusters, numIterations, tol, cluster_centers_0, random_state):
+
+    def is_string(m, target_):
+        return isinstance(m, string_types) and m == target_
+
+    def make_algo_token(dt, algo_name, csr):
+        """Constructs init algorithm name in DAAL"""
+        if dt == np.float64:
+            _type = 'Float64'
+        elif dt == np.float32:
+            _type = 'Float32'
+        else:
+            raise NotImplementedError('Unsupported input type %s' % dt)
+        csr_suffix = 'CSR' if csr else 'Dense'
+        return 'Batch_' + _type + algo_name + csr_suffix
+
+    def _compute_centroids_named(initAlg_callable, nClusters, dataTable):
+        """Given callable to initialization algorithm, compute initial cluster centers"""
+        if initAlg_callable is None:
+            raise ValueError('Failed to determine initialization method')
+        initAlg = initAlg_callable(nClusters)
+        initAlg.input.set(init.data, dataTable)
+        res = initAlg.compute()
+        centroids_ = res.get(init.centroids)
+        return centroids_
+
+    def _compute_starting_centroids(dataTable, cluster_centers_0, nClusters, dt, csr=False):
+        """Process initial clusters argument of KMeans, and either compute them using given algorithm"""
+        """ or consume explicitly given centers"""
+        if is_string(cluster_centers_0, 'k-means++'):
+            method_token = make_algo_token(dt, 'PlusPlus', csr)
+            initAlg_callable = getattr(init, method_token, None)
+            centroids_ = _compute_centroids_named(initAlg_callable, nClusters, dataTable)
+        elif is_string(cluster_centers_0, 'random'):
+            method_token = make_algo_token(dt, 'Random', csr)
+            initAlg_callable = getattr(init, method_token, None)
+            centroids_ = _compute_centroids_named(initAlg_callable, nClusters, dataTable)
+        elif hasattr(cluster_centers_0, '__array__'):
+            cc_arr = np.ascontiguousarray(cluster_centers_0, dtype=X.dtype)
+            _validate_center_shape(X, nClusters, cc_arr)
+            centroids_ = make_HomogenNumericTable(cc_arr)
+        elif callable(cluster_centers_0):
+            cc_arr = cluster_centers_0(X, nClusters, random_state)
+            cc_arr = np.ascontiguousarray(cc_arr, dtype=X.dtype)
+            _validate_center_shape(X, nClusters, cc_arr)
+            centroids_ = make_HomogenNumericTable(cc_arr)
+        elif is_string(cluster_centers_0, 'deterministic'):
+            method_token = make_algo_token(dt, 'Random', csr)
+            initAlg_callable = getattr(init, method_token, None)
+            centroids_ = _compute_centroids_named(initAlg_callable, nClusters, dataTable)
+        else:
+            raise ValueError("Cluster centers should either be 'k-means++', 'random', 'deterministic' or an array")
+        return centroids_
+
+    def _tolerance(X, rtol):
+        """Compute absolute tolerance from the relative tolerance"""
+        if rtol == 0.0:
+            return rtol
+        if sp.issparse(X):
+            variances = mean_variance_axis(X, axis=0)[1]
+        else:
+            variances = np.var(X, axis=0)
+        return np.mean(variances) * rtol
+
+    if numIterations < 0:
+        raise ValueError("Wrong iterations number")
+
+    if hasattr(X, '__array__'):
+        dataTable = make_HomogenNumericTable(X)
+        centroids_result = _compute_starting_centroids(dataTable, cluster_centers_0, nClusters, X.dtype, csr=False)
+
+        algorithm = Batch_Float32LloydDense(nClusters, numIterations) if X.dtype == np.float32 else Batch_Float64LloydDense(nClusters, numIterations)
+
+    elif sp.isspmatrix_csr(X):
+        dataTable = make_csr_table(X)
+        centroids_result = _compute_starting_centroids(dataTable, cluster_centers_0, nClusters, X.dtype, csr=True)
+
+        algorithm = Batch_Float32LloydCSR(nClusters, numIterations) if X.dtype == np.float32 else Batch_Float64LloydCSR(nClusters, numIterations)
+
+    else:
+        raise NotImplementedError("unsupported input type. you can disable pydaal with sklearn.daal4sklearn.dispatcher.disable()")
+
+    algorithm.parameter.maxIterations = numIterations
+    algorithm.parameter.accuracyThreshold = _tolerance(X, tol)
+    algorithm.parameter.assignFlag = True
+    algorithm.input.set(data, dataTable)
+    algorithm.input.set(inputCentroids, centroids_result)
+    res = algorithm.compute()
+
+    centroids_dtype = np.float32 if X.dtype == np.float32 else np.float64
+    labels = getArrayFromNumericTable(res.get(assignments))[:,0].astype(np.intc)
+    n_iter = int(getArrayFromNumericTable(res.get(nIterations))[0,0])
+    # Per documentation, with numIterations == 0, centroids and goalFunction are not updated
+    if numIterations > 0:
+        cluster_centers = getArrayFromNumericTable(res.get(centroids)).astype(centroids_dtype, copy = False)
+        inertia = getArrayFromNumericTable(res.get(goalFunction))[0,0]
+    else:
+        cluster_centers = None
+        inertia = None
+    return cluster_centers, labels, inertia, n_iter
+
+
+def _validate_center_shape(X, n_centers, centers):
+    """Check if centers is compatible with X and n_centers"""
+    if len(centers) != n_centers:
+        raise ValueError('The shape of the initial centers (%s) '
+                         'does not match the number of clusters %i'
+                         % (centers.shape, n_centers))
+    if centers.shape[1] != X.shape[1]:
+        raise ValueError(
+            "The number of features of the initial centers %s "
+            "does not match the number of features of the data %s."
+            % (centers.shape[1], X.shape[1]))
+
+
+def fit(self, x, y=None):
+    """compute k-means clustering.
+
+    parameters
+    ----------
+    x : array-like or sparse matrix, shape=(n_samples, n_features)
+    """
+    if self.n_init <= 0:
+        raise ValueError("Invalid number of initializations."
+                         " n_init=%d must be bigger than zero." % self.n_init)
+
+    random_state = check_random_state(self.random_state)
+    x = self._check_fit_data(x)
+
+    if self.max_iter <= 0:
+        raise ValueError('Number of iterations should be a positive number,'
+                         ' got %d instead' % self.max_iter)
+
+    if self.precompute_distances == 'auto':
+        precompute_distances = False
+    elif isinstance(self.precompute_distances, bool):
+        precompute_distances = self.precompute_distances
+    else:
+        raise ValueError("precompute_distances should be 'auto' or True/False"
+                         ", but a value of %r was passed" %
+                         self.precompute_distances)
+
+    daal_ready = hasattr(x, '__array__') or sp.isspmatrix_csr(x)
+    daal_ready = daal_ready and not precompute_distances
+
+    if not daal_ready:
+        self.cluster_centers_, self.labels_, self.inertia_, self.n_iter_ = \
+            k_means(
+                x, n_clusters=self.n_clusters, init=self.init,
+                n_init=self.n_init, max_iter=self.max_iter, verbose=self.verbose,
+                precompute_distances=precompute_distances,
+                tol=self.tol, random_state=random_state, copy_x=self.copy_x,
+                n_jobs=self.n_jobs, algorithm=self.algorithm,
+                return_n_iter=True)
+    else:
+        self.cluster_centers_, self.labels_, self.inertia_, self.n_iter_ = \
+            daal_k_means_dense(
+                x, self.n_clusters, self.max_iter, self.tol, self.init,
+                random_state)
+    return self
+
+
+def predict(self, X):
+    """Predict the closest cluster each sample in X belongs to.
+
+    In the vector quantization literature, `cluster_centers_` is called
+    the code book and each value returned by `predict` is the index of
+    the closest code in the code book.
+
+    Parameters
+    ----------
+    X : {array-like, sparse matrix}, shape = [n_samples, n_features]
+         New data to predict.
+
+    Returns
+    -------
+    labels : array, shape [n_samples,]
+        Index of the cluster each sample belongs to.
+    """
+    check_is_fitted(self, 'cluster_centers_')
+
+    X = self._check_test_data(X)
+
+    daal_ready = hasattr(X, '__array__') or sp.isspmatrix_csr(X)
+
+    if daal_ready:
+        return daal_k_means_dense(X, self.n_clusters, 0, 0.0, self.cluster_centers_, None)[1]
+    else:
+        x_squared_norms = row_norms(X, squared=True)
+        return _labels_inertia(X, x_squared_norms, self.cluster_centers_)[0]
diff --git a/sklearn/daal4sklearn/linear.py b/sklearn/daal4sklearn/linear.py
new file mode 100644
index 0000000000..89dfe5e920
--- /dev/null
+++ b/sklearn/daal4sklearn/linear.py
@@ -0,0 +1,158 @@
+import numpy as np
+from scipy import sparse as sp
+from scipy import linalg
+from .utils import getArrayFromNumericTable, make_HomogenNumericTable
+from ..utils import check_array, check_X_y, deprecated, as_float_array
+from daal.algorithms.linear_regression import training, prediction
+from ..linear_model.base import _rescale_data
+from ..externals.joblib import Parallel, delayed
+from ..utils.fixes import sparse_lsqr
+
+def make2d(X):
+    if X.ndim == 0:
+        X = X[np.newaxis, np.newaxis]
+    elif X.ndim == 1:
+        X = X.reshape((X.size, 1))
+    return X
+
+def daal_fit(self, X, y):
+    # Create Numeric Tables for training data and dependent variables
+    y = make2d(y)
+    trainData = make_HomogenNumericTable(X)
+    trainDependentVariables = make_HomogenNumericTable(y)
+    if X.dtype == np.float64:
+        algorithm = training.Batch_Float64NormEqDense()
+    elif X.dtype == np.float32:
+        algorithm = training.Batch_Float32NormEqDense()
+    # Create an algorithm object to train the multiple linear regression model with the normal equations method
+
+    # Pass a training data set and dependent values to the algorithm
+    algorithm.input.set(training.data, trainData)
+    algorithm.input.set(training.dependentVariables, trainDependentVariables)
+
+    # Build the multiple linear regression model and retrieve the algorithm results
+    algorithm.parameter.interceptFlag = self.fit_intercept
+    self.trainingResult_ = algorithm.compute()
+    self.coef_ = getArrayFromNumericTable(self.trainingResult_.get(training.model).getBeta())
+    if self.fit_intercept == True:
+        self.intercept_ = self.coef_[:,0]
+        self.coef_ = self.coef_[:,1:]
+    if self.coef_.shape[0] == 1:
+        self.coef_ = np.ravel(self.coef_)
+        self.intercept_ = self.intercept_[0]
+    return self
+
+
+def daal_predict(self, X):
+    # Create Numeric Tables for testing data and ground truth values
+    X = make2d(X)
+    testData = make_HomogenNumericTable(X)
+    # Create an algorithm object to predict values of multiple linear regression
+    algorithm = prediction.Batch()
+    # Pass a testing data set and the trained model to the algorithm
+
+    algorithm.input.setTable(prediction.data, testData)
+    algorithm.input.setModel(prediction.model, self.trainingResult_.get(training.model))
+    # Predict values of multiple linear regression and retrieve the algorithm results
+    predictionResult = algorithm.compute()
+    res = getArrayFromNumericTable(predictionResult.get(prediction.prediction))
+    if res.shape[1] == 1:
+        res = np.ravel(res)
+    return res
+
+def fit(self, X, y, sample_weight=None):
+    """
+    Fit linear model.
+
+    Parameters
+    ----------
+    X : numpy array or sparse matrix of shape [n_samples,n_features]
+        Training data
+
+    y : numpy array of shape [n_samples, n_targets]
+        Target values
+
+    sample_weight : numpy array of shape [n_samples]
+        Individual weights for each sample
+
+        .. versionadded:: 0.17
+           parameter *sample_weight* support to LinearRegression.
+
+    Returns
+    -------
+    self : returns an instance of self.
+    """
+
+    n_jobs_ = self.n_jobs
+    X, y = check_X_y(X, y, accept_sparse=['csr', 'csc', 'coo'],
+                     y_numeric=True, multi_output=True)
+
+    self.sample_weight_ = sample_weight
+    self.fit_shape_good_for_daal_ = True if X.shape[0] > X.shape[1] else False
+    if (self.fit_shape_good_for_daal_ and
+            not sp.issparse(X) and
+            self.fit_intercept and
+            (X.dtype == np.float64 or X.dtype == np.float32) and
+            sample_weight is None):
+        daal_fit(self, X, y)
+        return self
+
+    if sample_weight is not None and np.atleast_1d(sample_weight).ndim > 1:
+        raise ValueError("Sample weights must be 1D array or scalar")
+
+    X, y, X_offset, y_offset, X_scale = self._preprocess_data(
+        X, y, fit_intercept=self.fit_intercept, normalize=self.normalize,
+        copy=self.copy_X, sample_weight=sample_weight)
+
+    if sample_weight is not None:
+        # Sample weight can be implemented via a simple rescaling.
+        X, y = _rescale_data(X, y, sample_weight)
+
+    if sp.issparse(X):
+        if y.ndim < 2:
+            out = sparse_lsqr(X, y)
+            self.coef_ = out[0]
+            self._residues = out[3]
+        else:
+            # sparse_lstsq cannot handle y with shape (M, K)
+            outs = Parallel(n_jobs=n_jobs_)(
+                delayed(sparse_lsqr)(X, y[:, j].ravel())
+                for j in range(y.shape[1]))
+            self.coef_ = np.vstack(out[0] for out in outs)
+            self._residues = np.vstack(out[3] for out in outs)
+    else:
+        self.coef_, self._residues, self.rank_, self.singular_ = \
+            linalg.lstsq(X, y)
+        self.coef_ = self.coef_.T
+
+    if y.ndim == 1:
+        self.coef_ = np.ravel(self.coef_)
+    self._set_intercept(X_offset, y_offset, X_scale)
+    return self
+
+def predict(self, X):
+    """Predict using the linear model
+
+    Parameters
+    ----------
+    X : {array-like, sparse matrix}, shape = (n_samples, n_features)
+        Samples.
+
+    Returns
+    -------
+    C : array, shape = (n_samples,)
+        Returns predicted values.
+    """
+    X = np.asarray(X) if not sp.issparse(X) else X
+    good_shape_for_daal = True if X.ndim <= 1 else True if X.shape[0] > X.shape[1] else False
+
+    if (sp.issparse(X) or
+            not self.fit_intercept or
+            not self.fit_shape_good_for_daal_ or
+            not good_shape_for_daal or
+            not (X.dtype == np.float64 or X.dtype == np.float32) or
+            (hasattr(self, 'sample_weight_') and self.sample_weight_ is not None)):
+        return self._decision_function(X)
+    else:
+        X = check_array(X)
+        return daal_predict(self, X)
diff --git a/sklearn/daal4sklearn/pairwise.py b/sklearn/daal4sklearn/pairwise.py
new file mode 100644
index 0000000000..374b373471
--- /dev/null
+++ b/sklearn/daal4sklearn/pairwise.py
@@ -0,0 +1,134 @@
+from .utils import getArrayFromNumericTable, make_HomogenNumericTable
+from daal.data_management import HomogenNumericTable
+from daal.algorithms.cosine_distance import Batch as cos_Batch, cosineDistance, data as cos_data
+from daal.algorithms.correlation_distance import Batch as cor_Batch, correlationDistance, data as cor_data
+from ..metrics.pairwise import *
+from ..metrics.pairwise import _parallel_pairwise, _pairwise_callable
+from ..metrics.pairwise import _VALID_METRICS
+
+def daal_cosine_distance_dense(X):
+    dataTable = make_HomogenNumericTable(X)
+    algorithm = cos_Batch()
+    algorithm.input.set(cos_data, dataTable)
+    res = algorithm.compute()
+    return getArrayFromNumericTable(res.get(cosineDistance))
+
+def daal_correlation_distance_dense(X):
+    dataTable = make_HomogenNumericTable(X)
+    algorithm = cor_Batch()
+    algorithm.input.set(cor_data, dataTable)
+    res = algorithm.compute()
+    return getArrayFromNumericTable(res.get(correlationDistance))
+
+def daal_pairwise_distances(X, Y=None, metric="euclidean", n_jobs=1, **kwds):
+    """ Compute the distance matrix from a vector array X and optional Y.
+
+    This method takes either a vector array or a distance matrix, and returns
+    a distance matrix. If the input is a vector array, the distances are
+    computed. If the input is a distances matrix, it is returned instead.
+
+    This method provides a safe way to take a distance matrix as input, while
+    preserving compatibility with many other algorithms that take a vector
+    array.
+
+    If Y is given (default is None), then the returned matrix is the pairwise
+    distance between the arrays from both X and Y.
+
+    Valid values for metric are:
+
+    - From scikit-learn: ['cityblock', 'cosine', 'euclidean', 'l1', 'l2',
+      'manhattan']. These metrics support sparse matrix inputs.
+
+    - From scipy.spatial.distance: ['braycurtis', 'canberra', 'chebyshev',
+      'correlation', 'dice', 'hamming', 'jaccard', 'kulsinski', 'mahalanobis',
+      'matching', 'minkowski', 'rogerstanimoto', 'russellrao', 'seuclidean',
+      'sokalmichener', 'sokalsneath', 'sqeuclidean', 'yule']
+      See the documentation for scipy.spatial.distance for details on these
+      metrics. These metrics do not support sparse matrix inputs.
+
+    Note that in the case of 'cityblock', 'cosine' and 'euclidean' (which are
+    valid scipy.spatial.distance metrics), the scikit-learn implementation
+    will be used, which is faster and has support for sparse matrices (except
+    for 'cityblock'). For a verbose description of the metrics from
+    scikit-learn, see the __doc__ of the sklearn.pairwise.distance_metrics
+    function.
+
+    Read more in the :ref:`User Guide <metrics>`.
+
+    Parameters
+    ----------
+    X : array [n_samples_a, n_samples_a] if metric == "precomputed", or, \
+             [n_samples_a, n_features] otherwise
+        Array of pairwise distances between samples, or a feature array.
+
+    Y : array [n_samples_b, n_features], optional
+        An optional second feature array. Only allowed if metric != "precomputed".
+
+    metric : string, or callable
+        The metric to use when calculating distance between instances in a
+        feature array. If metric is a string, it must be one of the options
+        allowed by scipy.spatial.distance.pdist for its metric parameter, or
+        a metric listed in pairwise.PAIRWISE_DISTANCE_FUNCTIONS.
+        If metric is "precomputed", X is assumed to be a distance matrix.
+        Alternatively, if metric is a callable function, it is called on each
+        pair of instances (rows) and the resulting value recorded. The callable
+        should take two arrays from X as input and return a value indicating
+        the distance between them.
+
+    n_jobs : int
+        The number of jobs to use for the computation. This works by breaking
+        down the pairwise matrix into n_jobs even slices and computing them in
+        parallel.
+
+        If -1 all CPUs are used. If 1 is given, no parallel computing code is
+        used at all, which is useful for debugging. For n_jobs below -1,
+        (n_cpus + 1 + n_jobs) are used. Thus for n_jobs = -2, all CPUs but one
+        are used.
+
+    `**kwds` : optional keyword parameters
+        Any further parameters are passed directly to the distance function.
+        If using a scipy.spatial.distance metric, the parameters are still
+        metric dependent. See the scipy docs for usage examples.
+
+    Returns
+    -------
+    D : array [n_samples_a, n_samples_a] or [n_samples_a, n_samples_b]
+        A distance matrix D such that D_{i, j} is the distance between the
+        ith and jth vectors of the given matrix X, if Y is None.
+        If Y is not None, then D_{i, j} is the distance between the ith array
+        from X and the jth array from Y.
+
+    """
+    if (metric not in _VALID_METRICS and
+            not callable(metric) and metric != "precomputed"):
+        raise ValueError("Unknown metric %s. "
+                         "Valid metrics are %s, or 'precomputed', or a "
+                         "callable" % (metric, _VALID_METRICS))
+
+    if metric == "precomputed":
+        X, _ = check_pairwise_arrays(X, Y, precomputed=True)
+        return X
+    elif (metric == 'cosine') and (Y is None) and (not issparse(X)) and X.dtype == np.float64:
+        return daal_cosine_distance_dense(X)
+    elif (metric == 'correlation') and (Y is None) and (not issparse(X)) and X.dtype == np.float64:
+        return daal_correlation_distance_dense(X)
+    elif metric in PAIRWISE_DISTANCE_FUNCTIONS:
+        func = PAIRWISE_DISTANCE_FUNCTIONS[metric]
+    elif callable(metric):
+        func = partial(_pairwise_callable, metric=metric, **kwds)
+    else:
+        if issparse(X) or issparse(Y):
+            raise TypeError("scipy distance metrics do not"
+                            " support sparse matrices.")
+
+        dtype = bool if metric in PAIRWISE_BOOLEAN_FUNCTIONS else None
+
+        X, Y = check_pairwise_arrays(X, Y, dtype=dtype)
+
+        if n_jobs == 1 and X is Y:
+            return distance.squareform(distance.pdist(X, metric=metric,
+                                                      **kwds))
+        func = partial(distance.cdist, metric=metric, **kwds)
+
+    return _parallel_pairwise(X, Y, func, n_jobs, **kwds)
+
diff --git a/sklearn/daal4sklearn/pca.py b/sklearn/daal4sklearn/pca.py
new file mode 100644
index 0000000000..ce250cb5bb
--- /dev/null
+++ b/sklearn/daal4sklearn/pca.py
@@ -0,0 +1,83 @@
+import numpy as np
+from sklearn import decomposition
+from sklearn.decomposition.pca import *
+from .utils import getArrayFromNumericTable, make_HomogenNumericTable
+from ..decomposition.pca import _infer_dimension_
+from daal.data_management import HomogenNumericTable
+from daal.algorithms.svd import Batch, data, singularValues, rightSingularMatrix, leftSingularMatrix, Batch_Float32DefaultDense
+
+def daal_svd(matr):
+
+    dataTable = make_HomogenNumericTable(matr)
+
+    if matr.dtype == np.float64:
+        algorithm = Batch()
+    elif matr.dtype == np.float32:
+        algorithm = Batch_Float32DefaultDense()
+
+    algorithm.input.set(data, dataTable)
+    res = algorithm.compute()
+
+    s = np.ravel(getArrayFromNumericTable(res.get(singularValues)))
+    V = getArrayFromNumericTable(res.get(rightSingularMatrix))
+    U = getArrayFromNumericTable(res.get(leftSingularMatrix))
+    return U,s,V
+
+
+def _fit_full(self, X, n_components):
+    """Fit the model by computing full SVD on X"""
+    n_samples, n_features = X.shape
+
+    if n_components == 'mle':
+        if n_samples < n_features:
+            raise ValueError("n_components='mle' is only supported "
+                             "if n_samples >= n_features")
+    elif not 0 <= n_components <= n_features:
+        raise ValueError("n_components=%r must be between 0 and "
+                         "n_features=%r with svd_solver='full'"
+                         % (n_components, n_features))
+
+    # Center data
+    self.mean_ = np.mean(X, axis=0)
+    X -= self.mean_
+
+    if X.shape[0] > X.shape[1] and (X.dtype == np.float64 or X.dtype == np.float32):
+        U, S, V = daal_svd(X)
+    else:
+        U, S, V = linalg.svd(X, full_matrices=False) 
+    # flip eigenvectors' sign to enforce deterministic output
+    U, V = svd_flip(U, V)
+
+    components_ = V
+
+    # Get variance explained by singular values
+    explained_variance_ = (S ** 2) / (n_samples - 1)
+    total_var = explained_variance_.sum()
+    explained_variance_ratio_ = explained_variance_ / total_var
+
+    # Postprocess the number of components required
+    if n_components == 'mle':
+        n_components = \
+            _infer_dimension_(explained_variance_, n_samples, n_features)
+    elif 0 < n_components < 1.0:
+        # number of components for which the cumulated explained
+        # variance percentage is superior to the desired threshold
+        ratio_cumsum = explained_variance_ratio_.cumsum()
+        n_components = np.searchsorted(ratio_cumsum, n_components) + 1
+
+    # Compute noise covariance using Probabilistic PCA model
+    # The sigma2 maximum likelihood (cf. eq. 12.46)
+    if n_components < min(n_features, n_samples):
+        self.noise_variance_ = explained_variance_[n_components:].mean()
+    else:
+        self.noise_variance_ = 0.
+
+    self.n_samples_, self.n_features_ = n_samples, n_features
+    self.components_ = components_[:n_components]
+    self.n_components_ = n_components
+    self.explained_variance_ = explained_variance_[:n_components]
+    self.explained_variance_ratio_ = \
+        explained_variance_ratio_[:n_components]
+    self.singular_values_ = S[:n_components]
+
+    return U, S, V
diff --git a/sklearn/daal4sklearn/ridge.py b/sklearn/daal4sklearn/ridge.py
new file mode 100644
index 0000000000..1b643d5431
--- /dev/null
+++ b/sklearn/daal4sklearn/ridge.py
@@ -0,0 +1,123 @@
+import numpy as np
+from scipy import sparse as sp
+from .utils import getArrayFromNumericTable, make_HomogenNumericTable
+from ..utils import check_array, check_X_y, deprecated, as_float_array
+from daal.algorithms.ridge_regression import training, prediction
+from sklearn.linear_model.ridge import Ridge
+
+def make2d(X):
+    if X.ndim == 0:
+        X = X[np.newaxis, np.newaxis]
+    elif X.ndim == 1:
+        X = X.reshape((X.size, 1))
+    return X
+
+def daal_fit(self, X, y):
+
+    X = make2d(X)
+    y = make2d(y)
+    # Create Numeric Tables for training data and dependent variables
+    trainData = make_HomogenNumericTable(X)
+    trainDependentVariables = make_HomogenNumericTable(y)
+
+    # Create an algorithm object to train the multiple linear regression model with the normal equations method
+    algorithm = training.Batch_Float32NormEqDense() if X.dtype == np.float32 else training.Batch()
+
+    # Pass a training data set and dependent values to the algorithm
+    algorithm.input.set(training.data, trainData)
+    algorithm.input.set(training.dependentVariables, trainDependentVariables)
+
+    # Build the multiple linear regression model and retrieve the algorithm results
+    algorithm.parameter.interceptFlag = self.fit_intercept
+    #algorithm.parameter.ridgeParameters = make_HomogenNumericTable(np.array([[self.alpha]]))
+    ridge_params = np.asarray(self.alpha, dtype=X.dtype)
+    if ridge_params.size != 1 and ridge_params.size != y.shape[1]:
+        raise ValueError("alpha length wrong")
+    algorithm.parameter.ridgeParameters = make_HomogenNumericTable(ridge_params.reshape((1,ridge_params.size)))
+    self.trainingResult_ = algorithm.compute()
+    self.coef_ = getArrayFromNumericTable(self.trainingResult_.get(training.model).getBeta())
+    if self.fit_intercept == True:
+        self.intercept_ = self.coef_[:,0]
+        self.coef_ = self.coef_[:,1:]
+    if self.coef_.shape[0] == 1:
+        self.coef_ = np.ravel(self.coef_)
+        self.intercept_ = self.intercept_[0]
+    return self
+
+
+def daal_predict(self, X):
+    # Create Numeric Tables for testing data and ground truth values
+    X = make2d(X)
+    testData = make_HomogenNumericTable(X)
+    # Create an algorithm object to predict values of multiple linear regression
+    algorithm = prediction.Batch()
+    # Pass a testing data set and the trained model to the algorithm
+    algorithm.input.setTable(prediction.data, testData)
+
+    algorithm.input.setModel(prediction.model, self.trainingResult_.get(training.model))
+    # Predict values of multiple linear regression and retrieve the algorithm results
+    predictionResult = algorithm.compute()
+    res = getArrayFromNumericTable(predictionResult.get(prediction.prediction))
+    if res.shape[1] == 1:
+        res = np.ravel(res)
+    return res
+
+def fit(self, X, y, sample_weight=None):
+    """Fit Ridge regression model
+
+    Parameters
+    ----------
+    X : {array-like, sparse matrix}, shape = [n_samples, n_features]
+        Training data
+
+    y : array-like, shape = [n_samples] or [n_samples, n_targets]
+        Target values
+
+    sample_weight : float or numpy array of shape [n_samples]
+        Individual weights for each sample
+
+    Returns
+    -------
+    self : returns an instance of self.
+    """
+    X, y = check_X_y(X, y, ['csr', 'csc', 'coo'], dtype=[np.float64, np.float32],
+            multi_output=True, y_numeric=True)
+    self.sample_weight_ = sample_weight
+    self.fit_shape_good_for_daal_ = True if X.shape[0] > X.shape[1] else False
+    if (not self.solver == 'auto' or
+            not self.fit_intercept or
+            sp.issparse(X) or
+            not self.fit_shape_good_for_daal_ or
+            not (X.dtype == np.float64 or X.dtype == np.float32) or
+            sample_weight is not None):
+        return super(Ridge, self).fit(X, y, sample_weight=sample_weight)
+    else:
+        self.n_iter_ = None
+        return daal_fit(self, X, y)
+
+def predict(self, X):
+    """Predict using the linear model
+
+    Parameters
+    ----------
+    X : {array-like, sparse matrix}, shape = (n_samples, n_features)
+        Samples.
+
+    Returns
+    -------
+    C : array, shape = (n_samples,)
+        Returns predicted values.
+    """
+    X = check_array(X, accept_sparse=['csr', 'csc', 'coo'])
+    good_shape_for_daal = True if X.ndim <= 1 else True if X.shape[0] > X.shape[1] else False
+
+    if (not self.solver == 'auto' or
+            not self.fit_intercept or
+            sp.issparse(X) or
+            not good_shape_for_daal or
+            not self.fit_shape_good_for_daal_ or
+            not (X.dtype == np.float64 or X.dtype == np.float32) or
+            (hasattr(self, 'sample_weight_') and self.sample_weight_ is not None)):
+        return self._decision_function(X)
+    else:
+        return daal_predict(self, X)
diff --git a/sklearn/daal4sklearn/svm.py b/sklearn/daal4sklearn/svm.py
new file mode 100644
index 0000000000..f5c72d1bf6
--- /dev/null
+++ b/sklearn/daal4sklearn/svm.py
@@ -0,0 +1,391 @@
+from __future__ import print_function
+
+import numpy as np
+
+import daal.algorithms.svm as svm
+from scipy import sparse as sp
+
+from daal.algorithms import classifier, multi_class_classifier, kernel_function
+
+from .utils import make_HomogenNumericTable, getArrayFromNumericTable
+from ..utils import check_random_state, check_X_y
+
+
+LIBSVM_IMPL = ['c_svc', 'nu_svc', 'one_class', 'epsilon_svr', 'nu_svr']
+
+
+def make2d(X):
+    if X.ndim == 0:
+        X = X[np.newaxis, np.newaxis]
+    elif X.ndim == 1:
+        X = X[:, np.newaxis]
+    return X
+
+
+# Methods to extract coefficients
+def group_indices_by_class(num_classes, sv_ind_by_clf, labels):
+    sv_ind_counters = np.zeros(num_classes, dtype=np.intp)
+
+    num_of_sv_per_class = np.bincount(labels[np.hstack(sv_ind_by_clf)])
+    sv_ind_by_class = [np.empty(n, dtype=np.int32) for n in num_of_sv_per_class]
+
+    for indices_per_clf in sv_ind_by_clf:
+        for sv_index in indices_per_clf:
+            sv_label = labels[sv_index]
+            i = sv_ind_counters[sv_label]
+            sv_ind_by_class[sv_label][i] = sv_index
+            sv_ind_counters[sv_label] += 1
+
+    return sv_ind_by_class
+
+
+def map_sv_to_columns_in_dual_coef_matrix(sv_ind_by_class):
+    from collections import defaultdict
+    sv_ind_mapping = defaultdict(lambda: -1)
+    p = 0
+    for indices_per_class in sv_ind_by_class:
+        indices_per_class.sort()
+        for sv_index in indices_per_class:
+            if sv_ind_mapping[sv_index] == -1:
+                sv_ind_mapping[sv_index] = p
+                p += 1
+    return sv_ind_mapping
+
+
+def map_to_lexicographic(n):
+    """Returns permutation of reverse lexicographics to lexicographics orders for pairs of n consecutive integer indexes"""
+    from itertools import (combinations, count)
+    two_class_order_gen = ((j, i) for i in range(n) for j in range(i))
+    reverse_lookup = { key:val for key,val in zip(two_class_order_gen, count(0))}
+    perm_iter = (reverse_lookup[pair] for pair in combinations(range(n), 2))
+    return np.fromiter(perm_iter, dtype=np.intp)
+
+
+def permute_list(li, perm):
+    "Rearrange `li` according to `perm`"
+    return [ li[i] for i in perm ]
+
+
+def extract_dual_coef(num_classes, sv_ind_by_clf, sv_coef_by_clf, labels):
+    "Construct dual coefficients array in SKLearn peculiar layout, as well corresponding support vector indexes"
+    sv_ind_by_class = group_indices_by_class(num_classes, sv_ind_by_clf, labels)
+    sv_ind_mapping = map_sv_to_columns_in_dual_coef_matrix(sv_ind_by_class)
+
+    num_unique_sv = len(sv_ind_mapping)
+    dc_dt = sv_coef_by_clf[0].dtype
+
+    dual_coef = np.zeros((num_classes - 1, num_unique_sv), dtype=dc_dt)
+    support_ = np.empty((num_unique_sv,), dtype=np.int32)
+
+    p = 0
+    for i in range(0, num_classes):
+        for j in range(i + 1, num_classes):
+            sv_ind_i_vs_j = sv_ind_by_clf[p]
+            sv_coef_i_vs_j = sv_coef_by_clf[p]
+            p += 1
+
+            for k, sv_index in enumerate(sv_ind_i_vs_j):
+                label = labels[sv_index]
+                col_index = sv_ind_mapping[sv_index]
+                if j == label:
+                    row_index = i
+                else:
+                    row_index = j - 1
+                dual_coef[row_index, col_index] = sv_coef_i_vs_j[k]
+                support_[col_index] = sv_index
+
+    return dual_coef, support_
+
+
+def daal_fit(self, X, y, kernel):
+
+    if self.C <= 0:
+        raise ValueError("C <= 0")
+
+    y = make2d(y)
+    num_classes = len(self.classes_)
+
+    if num_classes == 2:
+        # Intel(R) DAAL requires binary classes to be 1 and -1. sklearn normalizes
+        # the classes to 0 and 1, so we temporarily replace the 0s with -1s.
+        y[y == 0] = -1
+
+    train_data = make_HomogenNumericTable(X)
+    train_ground_truth = make_HomogenNumericTable(y)
+
+    dtype = X.dtype
+    training_batch = svm.training.Batch(fptype=dtype)
+
+    training_batch.parameter.C = self.C
+    # Convert cache_size from MB to bytes.
+    training_batch.parameter.cacheSize = int(self.cache_size * 1024 * 1024)
+    training_batch.parameter.doShrinking = self.shrinking
+    training_batch.parameter.accuracyThreshold = self.tol
+    training_batch.parameter.tau = self.tol * (1e-3)
+
+    # Default to 2**30 iterations if self.max_iter is -1 (unlimited)
+    training_batch.parameter.maxIterations = self.max_iter if self.max_iter > 0 else 2**30
+
+    if kernel == 'rbf':
+        sigma_value = np.sqrt(0.5/self._gamma)
+        kf_rbf_algo1 = kernel_function.rbf.Batch(fptype=dtype)
+        kf_rbf_algo1.parameter.sigma = sigma_value
+        training_batch.parameter.kernel = kf_rbf_algo1
+    else:
+        training_batch.parameter.kernel = kernel_function.linear.Batch(fptype=dtype)
+
+    if num_classes == 2:
+        # Binary classifier
+        algorithm = training_batch
+    else:
+        # Multi-class classifier
+        algorithm = multi_class_classifier.training.Batch(num_classes, fptype=dtype)
+        algorithm.parameter.training = training_batch
+
+    algorithm.input.set(classifier.training.data, train_data)
+    algorithm.input.set(classifier.training.labels, train_ground_truth)
+
+    training_result = algorithm.compute()
+
+    model = training_result.get(classifier.training.model)
+    self._daal_model = model
+
+    if num_classes == 2:
+        two_class_sv_ind_ = getArrayFromNumericTable(model.getSupportIndices())
+        two_class_sv_ind_ = two_class_sv_ind_.ravel()
+
+        # support indexes need permutation to arrange them into the same layout as that of Scikit-Learn
+        tmp = np.empty(two_class_sv_ind_.shape, dtype=np.dtype([('label', y.dtype), ('ind', two_class_sv_ind_.dtype)]))
+        tmp['label'][:] = y[two_class_sv_ind_].ravel()
+        tmp['ind'][:] = two_class_sv_ind_
+        perm = np.argsort(tmp, order=['label', 'ind'])
+        del tmp
+        self.support_ = two_class_sv_ind_[perm]
+        self.support_vectors_ = X[self.support_]
+
+        self.dual_coef_ = getArrayFromNumericTable(model.getClassificationCoefficients())
+        self.dual_coef_ = self.dual_coef_[perm].T
+        self.intercept_ = np.array([model.getBias()])
+    else:
+        intercepts = []
+        coefs = []
+        num_models = model.getNumberOfTwoClassClassifierModels()
+        sv_ind_by_clf = []
+        label_indexes = []
+
+        model_id = 0
+        for i1 in range(num_classes):
+            label_indexes.append(np.where( y == i1 )[0])
+            for i2 in range(i1):
+                classifier_model = model.getTwoClassClassifierModel(model_id)
+                svm_model = svm.Model.downCast(classifier_model)
+
+                # Indices correspond to input features with label i1 followed by input features with label i2
+                two_class_sv_ind_ = getArrayFromNumericTable(svm_model.getSupportIndices())
+                # Map these indexes to indexes of the training data
+                sv_ind = np.take(np.hstack((label_indexes[i1], label_indexes[i2])), two_class_sv_ind_.ravel())
+                sv_ind_by_clf.append(sv_ind)
+
+                # svs_ = getArrayFromNumericTable(svm_model.getSupportVectors())
+                # assert np.array_equal(svs_, X[sv_ind])
+
+                intercepts.append(-svm_model.getBias())
+                coefs.append(-getArrayFromNumericTable(svm_model.getClassificationCoefficients()))
+                model_id += 1
+
+        # permute solutions to lexicographic ordering
+        to_lex_perm = map_to_lexicographic(num_classes)
+        sv_ind_by_clf = permute_list(sv_ind_by_clf, to_lex_perm)
+        sv_coef_by_clf = permute_list(coefs, to_lex_perm)
+        intercepts = permute_list(intercepts, to_lex_perm)
+
+        self.dual_coef_, self.support_ = extract_dual_coef(
+            num_classes,    # number of classes
+            sv_ind_by_clf,  # support vector indexes by two-class classifiers
+            sv_coef_by_clf, # classification coefficients by two-class classifiers
+            y.squeeze().astype(np.intp, copy=False)   # integer labels
+        )
+        self.support_vectors_ = X[self.support_]
+        self.intercept_ = np.array(intercepts)
+
+
+    indices = y.take(self.support_, axis=0)
+    if num_classes == 2:
+        self.n_support_ = np.array([np.sum(indices == -1), np.sum(indices == 1)], dtype=np.int32)
+    else:
+        self.n_support_ = np.array([np.sum(indices == c) for c in self.classes_], dtype=np.int32)
+
+    self.probA_ = np.empty(0)
+    self.probB_ = np.empty(0)
+
+    return training_result
+
+
+def fit(self, X, y, sample_weight=None):
+        """Fit the SVM model according to the given training data.
+        Parameters
+        ----------
+        X : {array-like, sparse matrix}, shape (n_samples, n_features)
+            Training vectors, where n_samples is the number of samples
+            and n_features is the number of features.
+            For kernel="precomputed", the expected shape of X is
+            (n_samples, n_samples).
+        y : array-like, shape (n_samples,)
+            Target values (class labels in classification, real numbers in
+            regression)
+        sample_weight : array-like, shape (n_samples,)
+            Per-sample weights. Rescale C per sample. Higher weights
+            force the classifier to put more emphasis on these points.
+        Returns
+        -------
+        self : object
+            Returns self.
+        Notes
+        ------
+        If X and y are not C-ordered and contiguous arrays of np.float64 and
+        X is not a scipy.sparse.csr_matrix, X and/or y may be copied.
+        If X is a dense array, then the other methods will not support sparse
+        matrices as input.
+        """
+        rnd = check_random_state(self.random_state)
+
+        sparse = sp.isspmatrix(X)
+        if sparse and self.kernel == "precomputed":
+            raise TypeError("Sparse precomputed kernels are not supported.")
+        self._sparse = sparse and not callable(self.kernel)
+
+        X, y = check_X_y(X, y, dtype=np.float64, order='C', accept_sparse='csr')
+        y = self._validate_targets(y)
+
+        sample_weight = np.asarray([]
+                                   if sample_weight is None
+                                   else sample_weight, dtype=np.float64)
+        solver_type = LIBSVM_IMPL.index(self._impl)
+
+        # input validation
+        if solver_type != 2 and X.shape[0] != y.shape[0]:
+            raise ValueError("X and y have incompatible shapes.\n" +
+                             "X has %s samples, but y has %s." %
+                             (X.shape[0], y.shape[0]))
+
+        if self.kernel == "precomputed" and X.shape[0] != X.shape[1]:
+            raise ValueError("X.shape[0] should be equal to X.shape[1]")
+
+        if sample_weight.shape[0] > 0 and sample_weight.shape[0] != X.shape[0]:
+            raise ValueError("sample_weight and X have incompatible shapes: "
+                             "%r vs %r\n"
+                             "Note: Sparse matrices cannot be indexed w/"
+                             "boolean masks (use `indices=True` in CV)."
+                             % (sample_weight.shape, X.shape))
+
+        if self.gamma == 'auto':
+            self._gamma = 1.0 / X.shape[1]
+        else:
+            self._gamma = self.gamma
+
+        kernel = self.kernel
+        if callable(kernel):
+            kernel = 'precomputed'
+
+        fit = self._sparse_fit if self._sparse else self._dense_fit
+        if self.verbose:  # pragma: no cover
+            print('[LibSVM]', end='')
+
+        # see comment on the other call to np.iinfo in this file
+        seed = rnd.randint(np.iinfo('i').max)
+
+        if ( not sparse and not self.probability and
+             sample_weight.size == 0 and self.class_weight is None and kernel in ['linear', 'rbf']):
+
+            self._daal_fit = True
+            daal_fit(self, X, y, kernel)
+        else:
+            self._daal_fit = False
+            fit(X, y, sample_weight, solver_type, kernel, random_seed=seed)
+
+
+        self.shape_fit_ = X.shape
+
+        # In binary case, we need to flip the sign of coef, intercept and
+        # decision function. Use self._intercept_ and self._dual_coef_ internally.
+        if not self._daal_fit:
+            self._intercept_ = self.intercept_.copy()
+            self._dual_coef_ = self.dual_coef_.copy()
+        else:
+            self._intercept_ = self.intercept_.copy()
+            self._dual_coef_ = self.dual_coef_.copy()
+            if len(self.classes_) == 2:
+                np.negative(self._dual_coef_, out=self._dual_coef_)
+
+        if not self._daal_fit and len(self.classes_) == 2 and self._impl in ['c_svc', 'nu_svc']:
+            self.intercept_ *= -1
+            self.dual_coef_ = -self.dual_coef_
+
+        return self
+
+try:
+    # corresponds to SKLearn's prediction based on scores
+    multi_class_pmethod = multi_class_classifier.prediction.voteBased
+except AttributeError:
+    multi_class_pmethod = multi_class_classifier.prediction.multiClassClassifierWu
+
+def daal_predict(self, X):
+
+    dtype = X.dtype
+    num_classes = len(self.classes_)
+    nt = make_HomogenNumericTable(X)
+
+    prediction_batch = svm.prediction.Batch(fptype=dtype)
+
+    if self.kernel == 'rbf':
+        sigma_value = np.sqrt(0.5/self._gamma)
+        prediction_batch.parameter.kernel = kernel_function.rbf.Batch(fptype=dtype, sigma=sigma_value)
+    else:
+        prediction_batch.parameter.kernel = kernel_function.linear.Batch(fptype=dtype)
+
+    if num_classes == 2:
+        algorithm = prediction_batch
+    else:
+        algorithm = multi_class_classifier.prediction.Batch(num_classes, fptype=dtype,
+                                                            pmethod=multi_class_pmethod)
+        algorithm.parameter.prediction = prediction_batch
+        algorithm.parameter.training = svm.training.Batch(fptype=dtype)
+
+    algorithm.input.setTable(classifier.prediction.data, nt)
+    algorithm.input.setModel(classifier.prediction.model, self._daal_model)
+
+    prediction_result = algorithm.compute()
+
+    res = getArrayFromNumericTable(prediction_result.get(classifier.prediction.prediction))
+    res = res.ravel()
+
+    if num_classes == 2:
+        # Convert from Intel(R) DAAL format back to original classes
+        np.greater(res, 0, out=res)
+
+    return res
+
+
+def predict(self, X):
+    """Perform regression on samples in X.
+
+    For an one-class model, +1 (inlier) or -1 (outlier) is returned.
+
+    Parameters
+    ----------
+    X : {array-like, sparse matrix}, shape (n_samples, n_features)
+        For kernel="precomputed", the expected shape of X is
+        (n_samples_test, n_samples_train).
+
+    Returns
+    -------
+    y_pred : array, shape (n_samples,)
+    """
+    X = self._validate_for_predict(X)
+    if self._daal_fit:
+        y = daal_predict(self, X)
+    else:
+        predict = self._sparse_predict if self._sparse else self._dense_predict
+        y = predict(X)
+
+    return self.classes_.take(np.asarray(y, dtype=np.intp))
diff --git a/sklearn/daal4sklearn/utils.py b/sklearn/daal4sklearn/utils.py
new file mode 100644
index 0000000000..8cba3128dd
--- /dev/null
+++ b/sklearn/daal4sklearn/utils.py
@@ -0,0 +1,57 @@
+import numpy as np
+from scipy import sparse as sp
+from daal.data_management import (readOnly, NumericTableIface, BlockDescriptor, BlockDescriptor_Float32, BlockDescriptor_Intc, packed_mask)
+from daal.data_management import (HomogenNumericTable, HomogenNumericTable_Float32, HomogenNumericTable_Intc, CSRNumericTable)
+
+def isFull(layout):
+    layout_int = int(layout)
+    if packed_mask & layout_int:
+        return False
+    return True
+
+
+def getArrayFromNumericTable(data_table):
+    num_rows = data_table.getNumberOfRows()
+    num_cols = data_table.getNumberOfColumns()
+    layout = data_table.getDataLayout()
+    data_table_dict = data_table.getDictionary()
+    try:
+        # see # https://software.intel.com/sites/products/documentation/doclib/daal/daal-user-and-reference-guides/daal_cpp_api/data__utils_8h_source.htm
+        # for numeral values of types
+        data_type = data_table_dict[0].indexType
+    except:
+        data_type = 1 # default to Float64
+
+    if data_type == 0:
+        block = BlockDescriptor_Float32()
+    elif data_type in [2, 4, 6, 8]:
+        block = BlockDescriptor_Intc()
+    else:
+        block = BlockDescriptor() # Use Float64 by default
+
+    data_table.getBlockOfRows(0, num_rows, readOnly, block)
+    retValue = block.getArray()
+    data_table.releaseBlockOfRows(block)
+
+    return retValue
+
+
+def make_csr_table(X):
+    if sp.isspmatrix_csr(X):
+        indices = np.array([x+1 for x in X.indices], dtype=np.uint64)
+        indptr =  np.array([x+1 for x in X.indptr], dtype=np.uint64)
+        return CSRNumericTable(X.data, indices, indptr, X.shape[1], X.shape[0])
+    return None
+
+
+def make_HomogenNumericTable(X):
+    X = np.ascontiguousarray(X)
+    if X.dtype == np.float64:
+        return HomogenNumericTable(X)
+    elif X.dtype == np.float32:
+        return HomogenNumericTable_Float32(X)
+    elif X.dtype == np.intc:
+        return HomogenNumericTable_Intc(X.astype(np.intc, copy=False))
+    else:
+        return HomogenNumericTable(X.astype(np.float64, copy=False))
+    return None
diff --git a/sklearn/mixture/tests/test_gaussian_mixture.py b/sklearn/mixture/tests/test_gaussian_mixture.py
index 821a7ce412..b635118c99 100644
--- a/sklearn/mixture/tests/test_gaussian_mixture.py
+++ b/sklearn/mixture/tests/test_gaussian_mixture.py
@@ -980,4 +980,4 @@ def test_init():
     gmm2 = GaussianMixture(n_components=n_components, n_init=100,
                            max_iter=1, random_state=random_state).fit(X)
 
-    assert_greater(gmm2.lower_bound_, gmm1.lower_bound_)
+    assert_greater_equal(gmm2.lower_bound_, gmm1.lower_bound_)
diff --git a/sklearn/setup.py b/sklearn/setup.py
index 8adbbd9d49..1985933dfc 100644
--- a/sklearn/setup.py
+++ b/sklearn/setup.py
@@ -40,6 +40,7 @@ def configuration(parent_package='', top_path=None):
     config.add_subpackage('preprocessing/tests')
     config.add_subpackage('semi_supervised')
     config.add_subpackage('semi_supervised/tests')
+    config.add_subpackage('daal4sklearn')
 
     # submodules which have their own setup.py
     # leave out "linear_model" and "utils" for now; add them after cblas below
diff --git a/sklearn/svm/tests/test_sparse.py b/sklearn/svm/tests/test_sparse.py
index f2c10ceddd..0252eee1d6 100644
--- a/sklearn/svm/tests/test_sparse.py
+++ b/sklearn/svm/tests/test_sparse.py
@@ -131,16 +131,16 @@ def test_svc_with_custom_kernel():
 def test_svc_iris():
     # Test the sparse SVC with the iris dataset
     for k in ('linear', 'poly', 'rbf'):
-        sp_clf = svm.SVC(kernel=k).fit(iris.data, iris.target)
-        clf = svm.SVC(kernel=k).fit(iris.data.toarray(), iris.target)
+        sp_clf = svm.SVC(kernel=k, tol=1e-8).fit(iris.data, iris.target)
+        clf = svm.SVC(kernel=k, tol=1e-8).fit(iris.data.toarray(), iris.target)
 
         assert_array_almost_equal(clf.support_vectors_,
                                   sp_clf.support_vectors_.toarray())
-        assert_array_almost_equal(clf.dual_coef_, sp_clf.dual_coef_.toarray())
+        assert_array_almost_equal(clf.dual_coef_, sp_clf.dual_coef_.toarray(), decimal=4)
         assert_array_almost_equal(
             clf.predict(iris.data.toarray()), sp_clf.predict(iris.data))
         if k == 'linear':
-            assert_array_almost_equal(clf.coef_, sp_clf.coef_.toarray())
+            assert_array_almost_equal(clf.coef_, sp_clf.coef_.toarray(), decimal=4)
 
 
 def test_sparse_decision_function():
@@ -303,6 +303,7 @@ def test_sparse_realdata():
     clf = svm.SVC(kernel='linear').fit(X.toarray(), y)
     sp_clf = svm.SVC(kernel='linear').fit(sparse.coo_matrix(X), y)
 
+    assert_array_equal(clf.support_, sp_clf.support_)
     assert_array_equal(clf.support_vectors_, sp_clf.support_vectors_.toarray())
     assert_array_equal(clf.dual_coef_, sp_clf.dual_coef_.toarray())
 
diff --git a/sklearn/svm/tests/test_svm.py b/sklearn/svm/tests/test_svm.py
index daf35f82a3..c061983e83 100644
--- a/sklearn/svm/tests/test_svm.py
+++ b/sklearn/svm/tests/test_svm.py
@@ -136,9 +136,9 @@ def test_precomputed():
     clf.fit(K, iris.target)
     clf2.fit(iris.data, iris.target)
     pred = clf.predict(K)
-    assert_array_almost_equal(clf.support_, clf2.support_)
-    assert_array_almost_equal(clf.dual_coef_, clf2.dual_coef_)
-    assert_array_almost_equal(clf.intercept_, clf2.intercept_)
+    assert_array_almost_equal(np.sort(clf.support_), np.sort(clf2.support_))
+    assert_array_almost_equal(clf.dual_coef_, clf2.dual_coef_, decimal=2)
+    assert_array_almost_equal(clf.intercept_, clf2.intercept_, decimal=2)
     assert_almost_equal(np.mean(pred == iris.target), .99, decimal=2)
 
     # Gram matrix for test data but compute KT[i,j]
@@ -342,7 +342,7 @@ def test_decision_function():
 
     rbfs = rbf_kernel(X, clf.support_vectors_, gamma=clf.gamma)
     dec = np.dot(rbfs, clf.dual_coef_.T) + clf.intercept_
-    assert_array_almost_equal(dec.ravel(), clf.decision_function(X))
+    assert_array_almost_equal(dec.ravel(), clf.decision_function(X), 3)
 
 
 def test_decision_function_shape():
@@ -430,7 +430,7 @@ def test_sample_weights():
     dual_coef_no_weight = clf.dual_coef_
     clf.set_params(C=100)
     clf.fit(X, Y, sample_weight=np.repeat(0.01, len(X)))
-    assert_array_almost_equal(dual_coef_no_weight, clf.dual_coef_)
+    assert_array_almost_equal(dual_coef_no_weight, clf.dual_coef_, decimal=2)
 
 
 def test_auto_weight():
diff --git a/sklearn/tests/test_common.py b/sklearn/tests/test_common.py
index dde6f4c41c..08a64ef96c 100644
--- a/sklearn/tests/test_common.py
+++ b/sklearn/tests/test_common.py
@@ -152,6 +152,7 @@ def test_all_tests_are_importable():
     HAS_TESTS_EXCEPTIONS = re.compile(r'''(?x)
                                       \.externals(\.|$)|
                                       \.tests(\.|$)|
+                                      \.daal4sklearn(\.|$)|
                                       \._
                                       ''')
     lookup = dict((name, ispkg)
