Create triangular matrix in tensorflow - matrix

I want to create a N * N lower triangular matrix with a length N*(N+1)/2 vector. I find tensorflow has a function tf.contrib.distributions.fill_triangular that achieves my goal.
However when I give
from tensorflow.contrib.distributions import fill_triangular
it says
cannot import name fill_triangular
My tensorflow version is 1.4.1. Can anyone let me know where is fill_triangular or how to create a N * N lower triangular matrix with a length N*(N+1)/2 vector?

fill_triangular is currently only available in the master version of Tensorflow (docs); it is not included even in the latest stable version 1.5 (docs), let alone 1.4.1.
You can build your matrix using numpy.tril_indices; here is an example with N=3:
import numpy as np
a = np.array([1, 2, 3, 4, 5, 6]) # this is your N*(N+1)/2 vector
tri = np.zeros((3,3)) # initialize an NxN zero matrix
tri[np.tril_indices(3, 0)] = a
tri
the result is
array([[ 1., 0., 0.],
[ 2., 3., 0.],
[ 4., 5., 6.]])

Related

How to solve for eigen value of a matrix numerically

I have a 3x3 matrix; I am interested in finding the eigen values and corresponding eigen vector numerically. I know for smaller system we can take determinant and will solve the determinant equation , which results in eigen values. But I have the matrix size which is pretty big; say 1000x1000. To show the problem, I have chosen 3x3 (which is dummy representation of the actual problem). Now how to compute the eigen values and eigen vectors in python.
import numpy as np
eg_matrix=np.array([[-2-x, -4, 2], [-2, 1-x, 2],[4,2,5-x]])
The system which is similar to my problem is; lambda_3 corresponds to eigen value.
You only give your matrix to the eigenvalue solver
import numpy as np
A=np.array([[-2, -4, 2], [-2, 1, 2],[4,2,5]])
x, V = np.linalg.eig(A)
assert np.allclose(V # np.diag(x), A # V)
For your example it gives x = array([-5., 3., 6.])
Each element of x plugged in the expression np.det(A - x * np.eye(len(A))) will be close to zero.
for instance
np.linalg.det(A - np.eye(len(A))*x[0])
gives 4.849454171562702e-13
V is the eigenvector matrix.

Discrete logarithmic colorbar in matplotlib

I want to create a pcolormesh plot with a discrete logarithmic colorbar. Some resolution is lost, but the matching between colors and values seems to be easier (at least for me) if the colormap is discrete.
The code snippet below produces a continuous log colormap with the preferred value range. How can I make it discrete? Here I found how to create a discrete linear colormap, but I couldn't extend it to log scale.
plt.pcolormesh(X,Y,Z,norm=mcolors.LogNorm(vmin=0.01, vmax=100.))
plt.colorbar()
fig = matplotlib.pyplot.gcf()
fig.set_size_inches(4*2.5, 3*2.5)
plt.xlabel("X", horizontalalignment='right', x=1.0)
plt.ylabel("Y", horizontalalignment='right', y=1.0)
plt.tight_layout()
I've managed to create a logarithmic colorbar with even spacing. However, I couldn't figure out how to create a discrete logarithmic colorbar with a logarithmic spacing of the colorbar. I hope this helps!
import matplotlib.pyplot as plt
import matplotlib as mpl
import numpy as np
X = np.arange(0, 50)
Y = np.arange(0, 50)
Z = np.random.rand(50, 50)*10
bounds = [0, 0.1, 0.2, 0.3, 0.4, 0.5, .7, .8, .9, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
num_c = len(bounds)
cmap = mpl.colormaps['viridis'].resampled(num_c)
norm = mpl.colors.BoundaryNorm(bounds, cmap.N)
fig, ax = plt.subplots()
fig.set_size_inches(4*2.5, 3*2.5)
ax.pcolormesh(X, Y, Z, norm=norm, cmap=cmap)
plt.xlabel("X", horizontalalignment='right', x=1.0)
plt.ylabel("Y", horizontalalignment='right', y=1.0)
fig.colorbar(mpl.cm.ScalarMappable(cmap=cmap, norm=norm))
plt.tight_layout()

Compute (Aᵀ×A)*(Bᵀ×B) matrix using gsl, Blas and Lapack

Let I have 2 symmetric matrices:
A = {{1,2}, {2,3}}
B = {{2,3},{3,4}}
Can I compute the matrix (AT×A)*(BT×B) using gsl, Blas and Lapack?
I'm using
gsl_blas_dsyrk(CblasUpper, CblasTrans, 1.0, A, 0.0, ATA);
gsl_blas_dsyrk(CblasUpper, CblasTrans, 1.0, B, 0.0, BTB);
gsl_blas_dsymm(CblasLeft, CblasUpper, 1.0, ATA, BTB, 0.0, ATABTB); // It doesn't work
It returns:
(Aᵀ·A) = ATA = {{5, 8}, {0, 13}} -- ok, gsl_blas_dsyrk returns symmetric matrix as upper triangular matrix.
(Bᵀ·B) = BTB = {{13, 8}, {0, 25}} -- ok.
(Aᵀ·A)·(Bᵀ·B) = ATABTB = {{65, 290}, {104, 469}} -- it's wrong.
Symmetrize BTB and the problem will be solved.
As you noticed, the upper triangular parts of symmetric matrices are computed by dsyrk(). Then dsymm() is applied. According to the definition of dsymm(), the following operation is performed since the flag CblasLeft is used:
C := alpha*A*B + beta*C
where alpha and beta are scalars, A is a symmetric matrix and B and
C are m by n matrices.
Indeed, the B matrix is a general matrix, not necessarly a symmetric one. As a result, ATA is multiplied by the upper triangular part of BTB, since the lower triangular part of BTB is not computed.
Symmetrize BTB and the problem will be solved. To do so, for loops is a straightforward solution , see Convert symmetric matrix between packed and full storage?

Finding an optimal selection in a 2D matrix with given constrains

Problem statement
Given a m x n matrix where m <= n you have to select entries so that their sum is maximal.
However you can only select one entry per row and at most one per column.
The performance is also a huge factor which means its ok to find selections that are not optimal in oder to reduce complexity (as long as its better than selecting random entries)
Example
Valid selections:
Invalid selections:
(one entry per row and at most one per column)
My Approaches
Select best of k random permutations
A = createRandomMatrix(m,n)
selections = list()
for try in range(k):
cols = createRandomIndexPermutation(m) # with no dublicates
for row in range(m):
sum += A[row, cols[row]]
selections.append(sum)
result = max(selections)
This appoach performs poorly when n is significantly larger than m
Best possible (not yet taken) column per row
A = createRandomMatrix(m,n)
takenCols = set()
result = 0
for row in range(m):
col = getMaxColPossible(row, takenCols, A)
result += A[row, col]
takenCols.add(col)
This approach always values the rows (or columns) higher that were discovered first which could lead to worse than average results
This sounds exactly like the rectangular linear assignment problem (RLAP). This problem can be efficiently (in terms of asymptotic complexity; somewhat around cubic time) solved (to a global-optimum) and a lot of software is available.
The basic approaches are LAP + dummy-vars, LAP-modifications or more general algorithms like network-flows (min-cost max-flow).
You can start with (pdf):
Bijsterbosch, J., and A. Volgenant. "Solving the Rectangular assignment problem and applications." Annals of Operations Research 181.1 (2010): 443-462.
Small python-example using python's common scientific-stack:
Edit: as mentioned in the comments, negating the cost-matrix (which i did, motivated by the LP-description) is not what's done in the Munkres/Hungarian-method literature. The strategy is to build a profit-matrix from the cost-matrix, which is now reflected in the example. This approach will lead to a non-negative cost-matrix (sometimes assumes; if it's important, depends on the implementation). More information is available in this question.
Code
import numpy as np
import scipy.optimize as sopt # RLAP solver
import matplotlib.pyplot as plt # visualizatiion
import seaborn as sns # """
np.random.seed(1)
# Example data from
# https://matplotlib.org/gallery/images_contours_and_fields/image_annotated_heatmap.html
# removed a row; will be shuffled to make it more interesting!
harvest = np.array([[0.8, 2.4, 2.5, 3.9, 0.0, 4.0, 0.0],
[2.4, 0.0, 4.0, 1.0, 2.7, 0.0, 0.0],
[1.1, 2.4, 0.8, 4.3, 1.9, 4.4, 0.0],
[0.6, 0.0, 0.3, 0.0, 3.1, 0.0, 0.0],
[0.7, 1.7, 0.6, 2.6, 2.2, 6.2, 0.0],
[1.3, 1.2, 0.0, 0.0, 0.0, 3.2, 5.1]],)
harvest = harvest[:, np.random.permutation(harvest.shape[1])]
# scipy: linear_sum_assignment -> able to take rectangular-problem!
# assumption: minimize -> cost-matrix to profit-matrix:
# remove original cost from maximum-costs
# Kuhn, Harold W.:
# "Variants of the Hungarian method for assignment problems."
max_cost = np.amax(harvest)
harvest_profit = max_cost - harvest
row_ind, col_ind = sopt.linear_sum_assignment(harvest_profit)
sol_map = np.zeros(harvest.shape, dtype=bool)
sol_map[row_ind, col_ind] = True
# Visualize
f, ax = plt.subplots(2, figsize=(9, 6))
sns.heatmap(harvest, annot=True, linewidths=.5, ax=ax[0], cbar=False,
linecolor='black', cmap="YlGnBu")
sns.heatmap(harvest, annot=True, mask=~sol_map, linewidths=.5, ax=ax[1],
linecolor='black', cbar=False, cmap="YlGnBu")
plt.tight_layout()
plt.show()
Output

Getting the coordinates for the "hottest areas" on a numpy heatmap

I've got a heat map numpy array with shape (600,400). The heatmap represents probabilities of detection. In my case, the probability of face detections in an image. My goal is to take this heatmap and get the coordinates (X and Y) where the highest probability occurs.
I've solved this for the case of a single face. The code for that is the following:
face_location = np.unravel_index(heatmap.argmax(), heatmap.shape)
print("Face location: " + str(face_location))
But in some cases there are multiple faces. I don't know how to adjust the algorithm to return multiple "hottest area". The issue is that any one hot area will be surrounded by gradually less hot areas. And so it's possible that after the hottest area, the next top 10 will all be right beside the initial point.
How can I adjust the algorithm to look for multiple hot areas? It's ok to assume that they won't be right beside each other.
heatmap = [[ 2.00299415e-04 2.03753079e-04 8.17560707e-04 ..., 2.23556344e-04
1.98958180e-04 9.92935777e-01]
[ 2.00642273e-04 2.04473894e-04 8.19963054e-04 ..., 2.24148811e-04
1.99438742e-04 9.92921114e-01]
[ 2.01056406e-04 2.05344462e-04 8.22864589e-04 ..., 2.24864416e-04
2.00019145e-04 9.92903233e-01]
...,
[ 7.28193991e-05 -2.73474743e-05 2.95096161e-05 ..., 5.96550672e-05
1.98282614e-05 9.99637246e-01]
[ 7.34055429e-05 -2.72389279e-05 3.02382941e-05 ..., 5.98490733e-05
2.04356711e-05 9.99619305e-01]
[ 7.37556256e-05 -2.71740992e-05 3.06735128e-05 ..., 5.99649393e-05
2.07984649e-05 9.99608397e-01]]
Perhaps consider using a mask array with a threshold probability defining the hot areas?
In [29]: threshold_probability = 0.8
In [30]: prng = np.random.RandomState(42)
In [31]: heatmap = prng.rand(600, 400)
In [32]: heatmap
Out[32]:
array([[ 0.37454012, 0.95071431, 0.73199394, ..., 0.42899403,
0.75087107, 0.75454287],
[ 0.10312387, 0.90255291, 0.50525237, ..., 0.56513318,
0.69665082, 0.92249938],
[ 0.70723863, 0.15253904, 0.57628836, ..., 0.96887786,
0.74965183, 0.13008624],
...,
[ 0.77669933, 0.98757844, 0.72686576, ..., 0.149866 ,
0.6685433 , 0.90248875],
[ 0.116007 , 0.96352904, 0.33109138, ..., 0.85776718,
0.88838363, 0.00901272],
[ 0.30810176, 0.43190563, 0.60935151, ..., 0.07498895,
0.60716006, 0.31712892]])
In [33]: hottest_areas = np.ma.MaskedArray(heatmap, heatmap < threshold_probability)
In [34]: X, Y = hottest_areas.nonzero()
In [35]: X
Out[35]: array([ 0, 0, 0, ..., 599, 599, 599])
In [36]: Y
Out[36]: array([ 1, 7, 11, ..., 376, 388, 394])
The result is a tuple containing the x and y coords of the values for which the boolean condition defining the mask is False (i.e., areas for which the probability of face is higher than threshold).
If you want to go with a threshold like davidrpugh proposed I have a different approach to propose.
Instead of finding the non zero elements, just find the connexe components of your binary image.
import numpy as np
from scipy.ndimage.measurements import label
from skimage.measure import regionprops
heatmap = np.random.rand(100, 25)
thresh = 0.9
bw = np.array(heatmap)
bw[bw < thresh] = 0
img_cc, nb_cc = label(bw)
cc = regionprops(img_cc)
face_location = np.array([c.centroid for c in cc])
import matplotlib.pyplot as plt
plt.figure()
plt.imshow(heatmap)
plt.plot(face_location[:, 1], face_location[:, 0], 'r*')
plt.figure()
plt.imshow(img_cc)
plt.plot(face_location[:, 1], face_location[:, 0], 'r*')
plt.show()
The face location are here defined by the centers of the connexe components but you can look for the maximum of each region in the image instead.

Resources