<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def predict_sequence(self, X, A, pi, inference='smoothing'):
 """ Calculate class probabilities for a sequence of data. Parameters X : array Test data, of dimension N times d (rows are time frames, columns are data dimensions) A : class transition matrix, where A[i,j] contains p(y_t=j|y_{t-1}=i) pi : vector of initial class probabilities inference : can be 'smoothing' or 'filtering'. Returns: ------- y_prob : array An array of dimension N times n_inlier_classes+1, containing the probabilities of each row of X being one of the inlier classes, or the outlier class (last column). """

        obsll = self.predict_proba(X)
        T, S = obsll.shape
        alpha = np.zeros((T, S))

        alpha[0, :] = pi
        for t in range(1, T):
            alpha[t, :] = np.dot(alpha[t-1, :], A)
            for s in range(S):
                alpha[t, s] *= obsll[t, s]
            alpha[t, :] = alpha[t, :]/sum(alpha[t, :])

        if inference == 'filtering':
            return alpha
        else:
            beta = np.zeros((T, S))
            gamma = np.zeros((T, S))
            beta[T-1, :] = np.ones(S)
            for t in range(T-2, -1, -1):
                for i in range(S):
                    for j in range(S):
                        beta[t, i] += A[i, j]*obsll[t+1, j]*beta[t+1, j]
                beta[t, :] = beta[t, :]/sum(beta[t, :])

            for t in range(T):
                gamma[t, :] = alpha[t, :]*beta[t, :]
                gamma[t, :] = gamma[t, :]/sum(gamma[t, :])

            return gamma