def __check_predict_actual_y(predict_y: ndarray, actual_y: ndarray, *, name: str = 'predict_y') \ -> Tuple[ndarray, ndarray]: predict_y = _t.c2r(predict_y) actual_y = _t.c2r(actual_y) if predict_y.shape[0] != actual_y.shape[0]: raise DataNotMatchError('number of %s and actual_y do not match' % name) return predict_y, actual_y
def compute_centroids(x_mat: ndarray, idx_vec: ndarray): """ 根据之前的聚类中心下标和样本,计算移动后的平均聚类中心值。 :param x_mat: 特征向量组,行数 m 表示样本数,列数 n 表示特征数 :param idx_vec: 聚类中心下标 :return: 新的聚类中心 """ x_mat = __t.r2m(x_mat) idx_vec = __t.c2r(idx_vec) m, n = x_mat.shape k = np.max(idx_vec) + 1 centroids = np.zeros((k, n)) cen_num = np.zeros((k, )) for i in range(m): centroids[idx_vec[i], :] = centroids[idx_vec[i], :] + x_mat[i, :] cen_num[idx_vec[i]] = cen_num[idx_vec[i]] + 1 for i in range(k): if cen_num[i] > 0: centroids[i, :] = centroids[i, :] / cen_num[i] return centroids
def feature_normalize(x_mat: ndarray, mean_row: ndarray = None, std_row: ndarray = None) \ -> Tuple[ndarray, ndarray, ndarray]: """ 将 x_mat 的特征规范化和归一化,也就是缩放以使得不同的参数之间差距不要太大。 如果参数 mean_col 和 std_col 都提供了的话,就使用它们进行规范;否则就计算新的 mean_col 和 std_col。 可以用在线性回归、SVM、PCA 中。 截距列不会被规范化。 :param x_mat: 特征向量组,行数 m 表示样本数,列数 n 表示特征数 :param mean_row: 每列特征值的平均值行向量 :param std_row: 每列特征值的标准行向量 :return: 规范化后的特征向量组,原来的特征向量组不会被影响;每个特征的平均值向量;每个特征的标准差向量 """ x_mat, has_ones = __t.delones(x_mat) if mean_row is not None: mean_row = __t.c2r(mean_row) if std_row is not None: std_row = __t.c2r(std_row) n = x_mat.shape[1] if mean_row is not None and std_row is not None and \ n != mean_row.shape[0] and mean_row.shape[0] != std_row.shape[0]: raise DataNotMatchError( 'x_mat\'s feature num does not match mean_row, std_row') # 转换数据类型防止计算精度丢失 x_norm = __t.i2f_dtype(x_mat.copy()) if mean_row is None and std_row is None: mean_row = np.mean(x_norm, axis=0) # ddof 设置为 1 表示计算样本方差,不设置表示计算总体方差 std_row = np.std(x_norm, ddof=1, axis=0) x_norm = (x_norm - mean_row) / std_row if has_ones: x_norm = np.hstack((np.ones((x_norm.shape[0], 1)), x_norm)) return x_norm, mean_row, std_row
def probability(self, x_mat: ndarray) -> Union[ndarray, float]: """ 返回对应于 x_mat 的预测概率。如果是二分类问题,那么返回一个行向量;如果是多分类问题,返回一个 m*num_labels 的矩阵,其中每一行表示样本在每个类上的概率。 :param x_mat: 特征向量组,行数 m 表示样本数,列数 n 表示特征数 :return: 预测概率。 """ if self._thetas is None: raise StateError('not trained yet') x_mat = _t.addones(x_mat) if x_mat.shape[1] - 1 != self.layer_nodes[0]: raise DataNotMatchError( 'feature number and input layer node number mismatch') return _t.ret(_t.c2r(self.__feedforward(self._thetas, x_mat)[-1]))
def predict(self, x_mat: ndarray) -> Union[ndarray, int]: """ 返回预测值,是对应于 x_mat 的标记。 :param x_mat: 特征向量组,行数 m 表示样本数,列数 n 表示特征数 :return: 预测标记 """ if self._thetas is None: raise StateError('not trained yet') x_mat = _t.addones(x_mat) if x_mat.shape[1] - 1 != self.layer_nodes[0]: raise DataNotMatchError( 'feature number and input layer node number mismatch') a = self.__feedforward(self._thetas, x_mat)[-1] if len(self.labels) == 2: return _t.ret( _t.convert_y(self.labels, _t.c2r(a >= self.threshold), to=False)) else: return _t.ret(self.labels[np.argmax(a, axis=1)])
def y_cv(self, value: Optional[ndarray]): if value is not None: self._y_cv = _t.c2r(value) else: self._y_cv = None