     }
 }
 
+template <typename T>
+__global__ void calculateTheta(T *d_gradient, T *d_theta, T factor, int theta_size){
+  int col = blockIdx.x * blockDim.x + threadIdx.x;
+  __shared__ T theta_0;
+  theta_0 = 0;
+  if (col < theta_size){
+    d_theta[col] = d_theta[col] - (factor * d_gradient[col]);
+  }
+}
 
   template <typename T>
   Vector<T> GpuLogisticRegression<T>::GpuFit(const Matrix<T> &xin, const Vector<T> &y,

    d_temp[col] = h(value) - d_y[col];
  }

  template <typename T>
  __global__ void calculateTheta(T *d_gradient, T *d_theta, T factor, int theta_size){
    int col = blockIdx.x * blockDim.x + threadIdx.x;
    __shared__ T theta_0;
    theta_0 = 0;
    if (col < theta_size){
      atomicAdd(&theta_0, d_theta[col]);
      if (col == 0){
        d_theta[0] = d_theta[0] - (factor * theta_0);
      }
      else{
        d_theta[col] = d_theta[col] - (factor * d_gradient[col - 1]);
      }
    }

  }


  /// Given a set of features and parameters creates a vector of target outputs
  ///
  /// \param inputs


        gradient(0) = h_sum;

        CUDA_CALL(cudaMalloc(&d_gradient, gradient.size() * sizeof(T)));
        CUDA_CALL(cudaMemcpy(d_gradient, &gradient(0), gradient.size() * sizeof(T),
          cudaMemcpyHostToDevice));

        calculateTheta<<< dimGrid, dimBlock>>>(d_gradient, d_theta, alpha/ y.size(), theta.size());

        CUDA_CALL(cudaMemcpy(&theta(0), d_theta, theta.size() * sizeof(T), cudaMemcpyDeviceToHost));
      }

      CUDA_CALL(cudaFree(d_xin));
