'Shapes not aligned in Python:

I'm new on stackoverflow and I'm trying to create a custom ridge regression model for a time series analysis. My goal is to predict the sign of stock return while using linear regression with ridge regularization. Details are below in the code. To perform my regression, I'm splitting my data into 5 equal blocks as training and test sets. In the for loop, I'm trying to cross validate my hyper parameters alpha and lambda to find best model in my ridge regression family. (As I'm new to Python, I couldn't make this in other simpler way. If you can correct my code in a simpler way, it would be better)

df =      [[5.029188 ,0.560895,-2.432905,-0.766467,4.97],
          [5.046780,-0.539126,-2.481951,-0.657977,4.990], 
          [5.270471,-0.398845,-2.622589,-1.455087,5.001],
          [5.450671,-0.336845,-2.352584,-1.235557,4.976],
          [5.247153,-0.653155,-2.246789,-1.164277,4.989],
          [5.797471,-0.498845,-2.432589,-1.555087,5.03],
          [5.350471,-0.598845,-2.672589,-1.655087,5.09],
          [5.320471,-0.698845,-2.234589,-1.755087,5.15],
          [5.650471,-0.798845,-2.765389,-1.355087,5.10],
          [5.760471,-0.898845,-2.223589,-1.255087,5.05],
          [5.225712,-0.198845,-2.876589,-1.155087,5.07],
          [5.650471,-0.298845,-2.345427,-1.455087,5.13],
          [5.122471,-0.356845,-2.586429,-1.567087,5.11],
          [5.890471,-0.543845,-2.454369,-1.123087,5.07],
          [5.240471,-0.235845,-2.543579,-1.789087,5.12],
          [5.980471,-0.654845,-2.245435,-1.245087,5.14],
          [5.120471,-0.876845,-2.466753,-1.323487,5.18],
          [5.650471,-0.234845,-2.235675,-1.355087,5.20],
          [5.432171,-0.765845,-2.353246,-1.765087,5.24],
          [5.765471,-0.458845,-2.356535,-1.245087,5.22],
          [5.029188 ,0.560895,-2.432905,-0.766467,5.21],
          [5.046780,-0.539126,-2.481951,-0.657977,5.32], 
          [5.270471,-0.398845,-2.622589,-1.455087,5.36],
          [5.450671,-0.336845,-2.352584,-1.235557,5.40],
          [5.247153,-0.653155,-2.246789,-1.164277,5.32],
          [5.797471,-0.498845,-2.432589,-1.555087,5.33],
          [5.350471,-0.598845,-2.672589,-1.655087,5.21],
          [5.320471,-0.698845,-2.234589,-1.755087,5.24],
          [5.650471,-0.798845,-2.765389,-1.355087,5.30],
          [5.760471,-0.898845,-2.223589,-1.255087,5.33],
          [5.225712,-0.198845,-2.876589,-1.155087,5.40],
          [5.650471,-0.298845,-2.345427,-1.455087,5.42],
          [5.122471,-0.356845,-2.586429,-1.567087,5.45],
          [5.890471,-0.543845,-2.454369,-1.123087,5.50],
          [5.240471,-0.235845,-2.543579,-1.789087,5.48],
          [5.980471,-0.654845,-2.245435,-1.245087,5.56],
          [5.120471,-0.876845,-2.466753,-1.323487,5.60],
          [5.650471,-0.234845,-2.235675,-1.355087,5.63],
          [5.432171,-0.765845,-2.353246,-1.765087,5.57],
          [5.765471,-0.458845,-2.356535,-1.245087,5.63]] 


  
# creating df object with columns specified    
data_new = pd.DataFrame(df, columns =['PC1', 'PC2','PC3','PC4','Price']) 

PC=['PC1','PC2','PC3','PC4']
   def ridge_regression(X, y, W, alpha=1, lambda_value=10, epochs=50):
    cost_hist=[]
    #W=initial weigths
    m = np.shape(X)[0]  # total number of samples
    n = np.shape(X)[1]  # total number of features
    
    X = np.concatenate((np.ones((m, 1)), X), axis=1)
 
    # iterate until the maximum number of epochs
    for current_iteration in np.arange(epochs):  # begin the process
 
        # compute the dot product between our feature 'X' and weight 'W'
        y_estimated = X.dot(W)
        
        y_estimated=pd.DataFrame(y_estimated)
        y=pd.DataFrame(y)
 
        # calculate the difference between the actual and predicted value
        sign_pred=np.sign(np.log(y_estimated)/np.log(y_estimated).shift(1)).fillna(0)
        sign_true=np.sign(np.log(y)/np.log(y).shift(1)).fillna(0)
        error = (sign_pred-sign_true)/m
        error=error.fillna(0)
        
        # regularization term
        ridge_reg_term = (lambda_value / 2 * m) * np.sum(np.square(W))
 
        # calculate the error + regularization term
        cost = (1 / 2 * m) * np.sum(error ** 2) + ridge_reg_term
 
        transpose=X.T
        dot_prod=pd.DataFrame(transpose.dot(error))
        gradient = (1 / m) * (dot_prod.iloc[:,0] + (lambda_value * W))
 
        # Now we have to update our weights
        W = W - alpha * gradient
        
        cost_hist.append(cost)
        
    weights=W
    
    return weights
    def BlockingTimeSeriesSplit(X,n_splits=5):
    train=[]
    test=[]
    for i in range(n_splits):
        n_samples = X.shape[0]
        k_fold_size = int(n_samples / n_splits)
        indices = np.arange(n_samples)
        start =i * k_fold_size
        stop = start + k_fold_size
        mid = int(0.5 * (stop - start)) + start
        train.append(indices[start: mid])
        test.append(indices[mid: stop])
    return train, test
n=5
f1_score=[]
alpha=[0.01,0.1,1,2,3,5,10,20,30,50,100,1000]
lambda_values=[1,2,3,5,10,20,30,50,100,200,300,500,1000]

a,b=BlockingTimeSeriesSplit(data_new,n)

for i in range(n):
    cv_train, cv_test = data_new.iloc[a[i]], data_new.iloc[b[i]]
    
    cv_validation,cv_test_new=train_test_split(cv_test,test_size=0.6)
    
    m_train=np.shape(cv_train[PC])[0]
    
    np.random.seed(11)
    W = np.random.randn(np.shape(cv_train[PC])[1] + 1, )
    
    weights_train=ridge_regression(cv_train[PC],cv_train['Price'],W)
    
    weights_train=pd.DataFrame(weights_train)
    
    
    for a in alpha:
        for l in lambda_values:
    
            weights_validation=ridge_regression(cv_validation[PC],cv_validation['Price'],weights_train,alpha=a,lambda_value=l)
    
            weights_validation=pd.DataFrame(weights_validation)
        
            m_valid=np.shape(cv_valid[PC])[0]
            X = np.concatenate((np.ones((m_valid, 1)), cv_train[PC]), axis=1)
    
            y_pred=pd.DataFrame(X.dot(weights_validation))
    
    
            # calculate the difference between the actual and predicted value
            sign_pred=np.sign(np.log(y_pred)/np.log(y_pred).shift(1)).fillna(0)
            sign_true=np.sign(np.log(cv_test['Price'])/np.log(cv_test['Price']).shift(1)).fillna(0)
    
            tn, fp, fn, tp =confusion_matrix(sign_true,sign_pred,labels=[0,1]).ravel()
            precision=tp/(tp+fp)
            recall=tp/(tp+fn)
            f1=2*(precision*recall)/(precision+recall)
            f1_score.append(f1)

    
            print("F1 Score: {}".format(np.mean(f1_score)))
        
return weights_validation

I'm receiving this error which is about the shape of the two dataframes:

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-439-08f7c7adf57f> in <module>
     25         for l in lambda_values:
     26 
---> 27             weights_validation=ridge_regression(cv_validation[PC],cv_validation['Price'],weights_train,alpha=a,lambda_value=l)
     28 
     29             weights_validation=pd.DataFrame(weights_validation)

<ipython-input-430-c693a48acc42> in ridge_regression(X, y, W, alpha, lambda_value, epochs)
     40 
     41         transpose=X.T
---> 42         dot_prod=pd.DataFrame(transpose.dot(error))
     43         gradient = (1 / m) * (dot_prod.iloc[:,0] + (lambda_value * W))
     44 
ValueError: shapes (11,23) and (46,2) not aligned: 23 (dim 1) != 46 (dim 0)

I'm struggling to understand how my error shape become (46,2) as when I trace back it, I see that it should be (23,1) and the dot production should be performed. I'm stuck at this point and looking forward to hearing your thoughts on that.



Solution 1:[1]

The last code:

transpose=X.T
transpose.dot(error)

from the error: (11,23) and (46,2)

So some how error is (46,2), while X is (23,10).

The challenge is to trace these arguments back to your inputs to the function

cv_validation[PC], cv_validation['Price'], weights_train

OK, X is cv_validation[PC]

Oops, I see that you did post ridge_regression. I haven't looked at that.

error = (sign_pred-sign_true)/m

Tracing dimensions thru those two inputs is more than I can readily do. Why are you using a dataframe here? Just to get the shift? I don't know if that complicates things.

You say error should be (23,1), but the error says it's (46,2). We can't verify that. You may need to add some diagnostic shape prints.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1