Say I have orthogonal vectors of dimension n. I have two questions:
How to create/initialize n such orthogonal vectors in python using the existing packages (numpy, scipy, pytorch etc)? Ideally these basis vectors should be as random as possible given the constraints, that is avoiding values such as 1,0,-1 as much as possible.
How can I rotate them by an angle alpha so that they remain orthogonal in high dimensional space? Again, I would like to do this in python, preferably using existing implementation in some of the packages.
You could do a QR decomposition of a random matrix, and set the R-component to zero. This will yield a random orthogonal matrix.
Vary one of the Givens angles in the Q components and you get a random rotation.
I have an answer to your first question and some thoughts on how to approach the second.
1.
import numpy as np
#let's say we're working in 5-D space
n = 5
#set of orthogonal basis vectors
basis_vectors = []
for _ in range(n):
vector = np.random.randn(n)
for basis_vector in basis_vectors:
vector -= basis_vector.dot(vector) * vector
#uncomment following to make basis orthonormal
#vector /= np.linalg.norm(rotation_axis)
basis_vectors.append(vector)
for a_i in range(n):
for b_i (a_i + 1, n):
assert np.allclose(basis_vectors[a_i].dot(basis_vectors[b_i]), 0)
Because you want to rotate both vectors in the same manner, there must be a way to preserve information on the way each rotation is carried out (e.g. rotation matrix, rotation quaternion).
Preexisting implementations of 3D Rotation matrices include the Scipy function scipy.spatial.transform.Rotation.from_rotvec and Python's quaternion module (see henneray's answer), but these are only for 3D vectors. Unless I've overlooked something, it'd be necessary to implement ND rotation from scratch.
Here's a general outline of the steps I would take:
Find 2 linearly independent ND basis vectors of the 2D plane in which you want to rotate the two vectors. (the vectors you want to rotate, a and b, aren't necessarily on this plane)
Find the remaining (N-2)D basis vectors that are linearly independent to these first 2 vectors. Combined the N basis vectors should span the ND space.
Break up each of the two N-D orthogonal vectors you want to rotate into the sum of two vectors: 1) the vectors' projections onto the 2D plane you've constructed and 2) the "remainder" of the vector that doesn't fall on the 2D plane. Set this "remainder" aside for now.
Perform a change of basis on the projected N-D vectors so that they can be expressed as the product of a 2D vector and an Nx2 matrix, which has its columns set to each of the corresponding basis vectors calculated. Keep in mind that the 2D vector is now in a modified coordinate space, not the original.
Construct the 2D rotation matrix corresponding to the desired rotation within the 2D plane identified in the first step. Perform the rotation transformation on the 2D vectors.
Transform the rotated 2D vectors back into ND vectors in the main coordinate system by multiplying the by the Nx2 matrix.
Add the "remainder" set aside earlier back to the mapped ND vector.
The resulting two vectors have been rotated by an arbitrary angle on a particular 2D plane, but maintain orthogonality.
I hope these ideas help you. Take care.
I found a scipy function that can do 1, ortho_group, still wondering about 2.
>>> from scipy.stats import ortho_group
>>> m = ortho_group.rvs(dim=4)
>>> m
array([[-0.25952499, 0.435163 , 0.04561972, 0.86092902],
[-0.44123728, -0.38814758, -0.80217271, 0.10568846],
[ 0.16909943, -0.80707234, 0.35548632, 0.44007851],
[-0.8422362 , -0.0927839 , 0.47756387, -0.23229737]])
>>> m.dot(m.T)
array([[ 1.00000000e+00, -1.68203864e-16, 1.75471554e-16,
9.74154717e-17],
[-1.68203864e-16, 1.00000000e+00, -1.18506045e-16,
-1.81879209e-16],
[ 1.75471554e-16, -1.18506045e-16, 1.00000000e+00,
1.16692720e-16],
[ 9.74154717e-17, -1.81879209e-16, 1.16692720e-16,
1.00000000e+00]])
I have a list of points xy with the shape(2,100). I want to take the dot product with a 2x2 matrix as follows:
g = xy.T#W#xy
which should result in a vector of 100 values. How can I do this with Python?
I know it should result in 100 values because the above express works well if I feed in one 2D point. How can I vectorize the above?
We can np.einsum -
np.einsum('ij,ik,kj->j',xy,W,xy, optimize=True)
I have a 2D array of values and I'm trying to analyze spatial correlations. To calculate a 2D autocorrelation like Moran's I in python, pysal provides an implementation.
1) How do I transform my 2D data into a 1D array expected by pysal?
2) How do I construct a weight array w that is based on distance (what does the input array of points mean in the Kernel distance function?)?
1) The weights array should be flattened in the same way as you flatten the data array. The order doesn't matter, as long as the indices agree.
2) The input array can be spatial coordinates (e.g. x and y, or lat and long). By far the easiest are the indices of your original matrix (e.g. 1 to n times 1 to m).
In the end, your data will be a list with 3 elements: x, y and value. Your weights will be a list with 5 elements: x_from, y_from, x_to, y_to and weight.
I have a numpy ndarray object with the following shape:
(3, 256, 170, 256).
So, basically this represents an array of 3-dimensional vectors. The dimension of the vector is the first element as it enables one to write something like: array[0] for the relevant vector component.
Now, I am trying to use scipy pdist function, which computes the distance between the entries. So, I need to modify this array, so that it can be represented as a two dimensional matrix, where the number of rows is 256*170*256 and the number of columns is 3 and pdist should return me the matrix where each element is the squared distance between the corresponding 3 dimensional vectors (if I have interpreted the documentation correctly).
Can someone tell me how I can get a view into this numpy array, so that I can generate this matrix. I do not want to copy the data again (as these matrices can be quite large), so looking for some efficient solutions.
I'm still getting the hang of working with numpy and array-wise operations.
I'm looking for the way of getting the row-wise average of a list of 2D arrays.
E.g I have a 4x3x25 array and I'm looking to get a 3x25 array of the row-wise averages.
If everything’s in one 3D array already, you can just do:
A.mean(axis=0)
…which will operate along the first dimension.
If it’s actually just a list of 2D arrays, you’ll have to convert it to a 3D array first. I would do:
A = np.dstack(list_of_arrays) # Combine the 2D arrays along a new 3rd dimension
A.mean(axis=2) # Calculate the means along that new dimension