Chromium Code Reviews| Index: appengine/findit/crash/changelist_features/top_frame_index.py |
| diff --git a/appengine/findit/crash/changelist_features/top_frame_index.py b/appengine/findit/crash/changelist_features/top_frame_index.py |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..5873550eeafd78c625fcc753e439837ee155156f |
| --- /dev/null |
| +++ b/appengine/findit/crash/changelist_features/top_frame_index.py |
| @@ -0,0 +1,79 @@ |
| +# Copyright 2016 The Chromium Authors. All rights reserved. |
| +# Use of this source code is governed by a BSD-style license that can be |
| +# found in the LICENSE file. |
| + |
| + |
| +# TODO(katesonia): Move this to the config saved in datastore. |
| +_MAX_FRAME_INDEX = 7 |
| + |
| + |
| +class TopFrameIndexFeature(object): |
| + """Return the minimum frame index scaled linearly between 0 and 1. |
| + |
| + That is, when the smallest ``StackFrame.index`` across all files |
| + and stacktraces is 0 we return 1; when it is greater than the |
| + ``max_frame_index`` passed to the constructor, we return 0. And in |
| + between we return values linearly interpolated between those points. |
| + |
| + In principle this normalization isn't strictly required, as the weight |
| + of this feature can be be scaled to account for the normalization. |
| + However, by normalizing things we ensure that the feature's weight is |
| + independent of ``max_frame_index``, which helps training. |
| + """ |
| + |
| + def __init__(self, max_frame_index=None): |
| + """ |
| + Args: |
| + max_frame_index (int): An upper bound on the minimum frame index |
| + to consider. This argument is optional and defaults to |
| + ``_MAX_FRAME_INDEX``. |
| + """ |
| + if max_frame_index is None: |
| + max_frame_index = _MAX_FRAME_INDEX |
|
inferno
2016/12/06 18:07:06
init in constructor
|
| + self.max_frame_index = float(max_frame_index) |
|
Sharu Jiang
2016/12/06 20:49:19
why converting the max_frame_index to float here?
wrengr
2016/12/07 00:55:38
I was waffling back and forth on whether to do it
|
| + |
| + def __call__(self, result): |
| + """The minimum ``StackFrame.index`` across all files and stacks. |
| + |
| + Although this looks like it should be a method on the ``Result`` |
| + class itself, we have it be a standalone function in order to make |
| + coverage tests happy. The downside of this is that we now have to |
| + modify multiple files whenever the guts of ``Result`` change. The |
| + upside is the aforementioned coverage tests, and that it helps |
| + keep the ``Result`` class looking cleaner. |
| + |
| + Args: |
| + result (Result): the result to analyze. |
| + |
| + Returns: |
| + The minimum frame index, as a ``float``. If the ``Result`` has |
| + no frames or if the true minimum frame index is greater than |
| + ``max_frame_index``, then we return zero. Otherwise the final |
| + value is scaled linearly between 0 and 1. |
| + """ |
| + if not result.file_to_stack_infos: |
| + return 0. |
| + |
| + top_frame_index = min(self.max_frame_index, |
| + float(min(min(frame.index for frame, _ in stack_infos) |
| + for stack_infos in result.file_to_stack_infos.itervalues()))) |
| + |
| + return (self.max_frame_index - top_frame_index) / self.max_frame_index |
| + |
| + |
| +class SquaredTopFrameIndexFeature(TopFrameIndexFeature): |
| + """Return the minimum frame index scaled quadratically between 0 and 1. |
| + |
| + This feature together with ``TopFrameIndexFeature`` (and a constant |
| + feature) allow us to capture any quadratic polynomial of the |
| + ``TopFrameIndex``. That is, suppose we had a single feature ``c2*x**2 + |
| + c1*x + 1`` with weight ``w``. Rather than using that feature directly |
| + (which would require us to specify the hyperparameters ``c2`` and |
| + ``c1``) we can instead use three features: ``w2*(x**2) + w1*x + w0``; |
|
Sharu Jiang
2016/12/06 20:49:19
Just a thought, we can also use kernel to achieve
wrengr
2016/12/07 00:55:38
We could use some kernel tricks to generate a whol
|
| + which enables us to avoid specifying the hyperparameters, by pushing |
| + them into the weight parameters instead. |
| + """ |
| + def __call__(self, result): |
| + linear_top_frame_index = ( |
| + super(SquaredTopFrameIndexFeature, self).__call__(result)) |
| + return linear_top_frame_index * linear_top_frame_index |