Help on return type(?)
Martin A. Brown
martin at linux-ip.net
Sat Jan 9 22:10:42 EST 2016
Hello there,
>> def make_cov(cov_type, n_comp, n_fea):
>> mincv = 0.1
>> rand = np.random.random
>> return {
>> 'spherical': (mincv + mincv * np.dot(rand((n_components, 1)),
>> np.ones((1, n_features)))) **
>> 2,
>> 'tied': (make_spd_matrix(n_features)
>> + mincv * np.eye(n_features)),
>> 'diag': (mincv + mincv * rand((n_components, n_features))) ** 2,
>> 'full': np.array([(make_spd_matrix(n_features)
>> + mincv * np.eye(n_features))
>> for x in range(n_components)])
>> }[cov_type]
>>
>> Specifically, could you explain the meaning of
>>
>> {
>> ... }[cov_type]
>>
>> to me?
>
>It is a dictionary lookup. { ... } sets up a dictionary with keys
>
> 'spherical'
> 'tied'
> 'diag'
> 'full'
>
>then { ... }[cov_type] extracts one of the values depending on
>whether cov_type is 'spherical', 'tied', 'diag', or 'full'.
You will see that Steven has answered your question. I will add to
his answer.
Your original function could be improved many ways, but especially
in terms of readability. Here's how I might go at improving the
readability, without understanding anything about the actual
computation.
def make_cov_spherical(mincv, n_components, n_features):
return (mincv + mincv * np.dot(np.random.random((n_components, 1)), np.ones((1, n_features)))) ** 2
def make_cov_diag(mincv, n_components, n_features):
return (mincv + mincv * np.random.random((n_components, n_features))) ** 2
def make_cov_tied(mincv, n_components, n_features):
return make_spd_matrix(n_features) + mincv * np.eye(n_features)
def make_cov_full(mincv, n_components, n_features):
return np.array([(make_spd_matrix(n_features) + mincv * np.eye(n_features)) for x in range(n_components)])
def make_cov(cov_type, n_comp, n_fea):
mincv = 0.1
dispatch_table = {
'spherical': make_cov_spherical,
'tied': make_cov_tied,
'diag': make_cov_diag,
'full': make_cov_full,
}
func = dispatch_table[cov_type]
return func(mincv, n_comp, n_fea)
Some thoughts (and reaction to the prior code):
* Your originally posted code referred to n_comp and n_fea in the
signature, but then used n_components and n_features in the
processing lines. Did this function ever work?
* Individual functions are easier to read and understand. I would
find it easier to write testing code (and docstrings) for these
functions, also.
* The assignment of a name (rand = np.random.random) can make
sense, but I think it simply shows that the original function
was trying to do too many things and was hoping to save space
with this shorter name for the np.random.random. Not bad, but I
dropped it anyway for the sake of clarity.
* Each of the above functions (which I copied nearly verbatim)
could probably now be broken into one or two lines. That would
make the computation even clearer.
* There may be a better way to make a function dispatch table than
the one I demonstrate above, but I think it makes the point
nicely.
* If you break the individual computations into functions, then
you only run the specific computation when it's needed. In the
original example, all of the computations were run AND then, one
of the results was selected. It may not matter, since computers
are so fast, but, practicing basic parsimony can avoid little
obvious performance hazards like this.
* In short, longer, but much much clearer.
Good luck,
-Martin
--
Martin A. Brown
http://linux-ip.net/
More information about the Python-list
mailing list