1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168
|
# Author: Mathieu Blondel
# Olivier Grisel
#
# License: BSD Style.
cimport numpy as np
import numpy as np
cimport cython
cdef extern from "math.h":
double fabs(double f)
double sqrt(double f)
ctypedef np.float64_t DOUBLE
@cython.boundscheck(False)
@cython.wraparound(False)
@cython.cdivision(True)
def mean_variance_axis0(X):
"""Compute mean and variance along axis 0 on a CSR matrix
Parameters
----------
X: CSR sparse matrix, shape (n_samples, n_features)
Input data.
Returns
-------
means: float array with shape (n_features,)
Feature-wise means
variances: float array with shape (n_features,)
Feature-wise variances
"""
cdef unsigned int n_samples = X.shape[0]
cdef unsigned int n_features = X.shape[1]
cdef np.ndarray[DOUBLE, ndim=1] X_data = X.data
cdef np.ndarray[int, ndim=1] X_indices = X.indices
cdef np.ndarray[int, ndim=1] X_indptr = X.indptr
cdef unsigned int i
cdef unsigned int j
cdef unsigned int ind
cdef double diff
# means[j] contains the mean of feature j
cdef np.ndarray[DOUBLE, ndim=1] means = np.asarray(X.mean(axis=0))[0]
# variances[j] contains the variance of feature j
cdef np.ndarray[DOUBLE, ndim=1] variances = np.zeros_like(means)
# counts[j] contains the number of samples where feature j is non-zero
counts = np.zeros_like(means)
for i in xrange(n_samples):
for j in xrange(X_indptr[i], X_indptr[i + 1]):
ind = X_indices[j]
diff = X_data[j] - means[ind]
variances[ind] += diff * diff
counts[ind] += 1
nz = n_samples - counts
variances += nz * means ** 2
variances /= n_samples
return means, variances
@cython.boundscheck(False)
@cython.wraparound(False)
@cython.cdivision(True)
def inplace_csr_row_normalize_l1(X):
"""Inplace row normalize using the l1 norm"""
cdef unsigned int n_samples = X.shape[0]
cdef unsigned int n_features = X.shape[1]
cdef np.ndarray[DOUBLE, ndim=1] X_data = X.data
cdef np.ndarray[int, ndim=1] X_indices = X.indices
cdef np.ndarray[int, ndim=1] X_indptr = X.indptr
# the column indices for row i are stored in:
# indices[indptr[i]:indices[i+1]]
# and their corresponding values are stored in:
# data[indptr[i]:indptr[i+1]]
cdef unsigned int i
cdef unsigned int j
cdef double sum_
for i in xrange(n_samples):
sum_ = 0.0
for j in xrange(X_indptr[i], X_indptr[i + 1]):
sum_ += fabs(X_data[j])
if sum_ == 0.0:
# do not normalize empty rows (can happen if CSR is not pruned
# correctly)
continue
for j in xrange(X_indptr[i], X_indptr[i + 1]):
X_data[j] /= sum_
@cython.boundscheck(False)
@cython.wraparound(False)
@cython.cdivision(True)
def inplace_csr_row_normalize_l2(X):
"""Inplace row normalize using the l2 norm"""
cdef unsigned int n_samples = X.shape[0]
cdef unsigned int n_features = X.shape[1]
cdef np.ndarray[DOUBLE, ndim=1] X_data = X.data
cdef np.ndarray[int, ndim=1] X_indices = X.indices
cdef np.ndarray[int, ndim=1] X_indptr = X.indptr
cdef unsigned int i
cdef unsigned int j
cdef double sum_
for i in xrange(n_samples):
sum_ = 0.0
for j in xrange(X_indptr[i], X_indptr[i + 1]):
sum_ += (X_data[j] * X_data[j])
if sum_ == 0.0:
# do not normalize empty rows (can happen if CSR is not pruned
# correctly)
continue
sum_ = sqrt(sum_)
for j in xrange(X_indptr[i], X_indptr[i + 1]):
X_data[j] /= sum_
@cython.boundscheck(False)
@cython.wraparound(False)
@cython.cdivision(True)
def inplace_csr_column_scale(X, np.ndarray[DOUBLE, ndim=1] scale):
"""Inplace column scaling of a CSR matrix.
Scale each feature of the data matrix by multiplying with specific scale
provided by the caller assuming a (n_samples, n_features) shape.
Parameters
----------
X: CSR matrix with shape (n_samples, n_features)
Matrix to normalize using the variance of the features.
scale: float array with shape (n_features,)
Array of precomputed feature-wise values to use for scaling.
"""
cdef unsigned int n_samples = X.shape[0]
cdef unsigned int n_features = X.shape[1]
cdef np.ndarray[DOUBLE, ndim=1] X_data = X.data
cdef np.ndarray[int, ndim=1] X_indices = X.indices
cdef np.ndarray[int, ndim=1] X_indptr = X.indptr
cdef unsigned int i, j
for i in xrange(n_samples):
for j in xrange(X_indptr[i], X_indptr[i + 1]):
X_data[j] *= scale[X_indices[j]]
|