{"id":404804,"date":"2024-06-29T17:56:22","date_gmt":"2024-06-29T17:56:22","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=404804"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=404804","title":{"rendered":"<span>GNU radio 802.11 black box optimization<\/span>"},"content":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<h2>What this all is about<\/h2>\n<p>In this post I&#8217;ll share my experience in adjustment of  WiFi physical channel. The channel was  implemented on a software defined radio (SDR) platform. WiFi looks like a very complicated thing standardized over hundreds of pages. Could a non-expert with PC and a couple of 100$ devices somehow improve it? <\/p>\n<p>I tried to answer the question experimentally. Gaussian processes were engaged to process noisy and time-consuming channel quality measurements. The work results could be used to finely adjust WiFi channel quality. Project code is available at <a href=\"https:\/\/github.com\/KVasya\/AdjustableWiFi\/tree\/gpflow\" rel=\"noopener noreferrer nofollow\">https:\/\/github.com\/KVasya\/AdjustableWiFi\/tree\/gpflow<\/a> .<\/p>\n<h2>Software and hardware involved<\/h2>\n<p>My experiments were based on GNU radio (GR, <a href=\"https:\/\/www.gnuradio.org\/\" rel=\"noopener noreferrer nofollow\">https:\/\/www.gnuradio.org\/<\/a>) implementation of IEEE 802.11 protocol (aka WiFi, <a href=\"https:\/\/github.com\/bastibl\/gr-ieee802-11\" rel=\"noopener noreferrer nofollow\">https:\/\/github.com\/bastibl\/gr-ieee802-11<\/a> by Bastibl). GR enables you to configure a relatively cheap  radio device for WiFi signals. The <a href=\"https:\/\/github.com\/bastibl\/gr-ieee802-11\" rel=\"noopener noreferrer nofollow\">gr-ieee802-11<\/a> implementation in principle reveals all the internal stages of WiFi signal treatment. If we wanted to optimize it, a decent way would be to go deep into the project and see what&#8217;s going on with the signal. A different way is to consider WiFi implementation as a black box and optimize it&#8217;s performance by trying many different project parameter values. This way one actually works with a project facing it for the first time.   My intention was to find a mathematical framework for such a triage of complicated GR projects. If useful, such a functionality could be  wrapped in a standard GR block. <\/p>\n<p>I took 2 HackRF  devices (one for transmissions and one for reception, Fig. 0) and changed <a href=\"https:\/\/github.com\/bastibl\/gr-ieee802-11\" rel=\"noopener noreferrer nofollow\">gr-ieee802-11<\/a> into echo configuration: a short text message is encoded into physical signal, sent through transmitting device, then it&#8217;s caught by receiving device, and then decoded back into text (GNU radio project is shown in Fig. 1). The devices operated in 2.4GHz WiFi frequency range.<\/p>\n<figure class=\"bordered full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/31a\/930\/bb1\/31a930bb11eba4edc7e0ea8672138ddf.png\" alt=\"Figure 0. Experimental setup. Two HackRF (https:\/\/greatscottgadgets.com\/hackrf\/) devices connected to host notebook PC.\" title=\"Figure 0. Experimental setup. Two HackRF (https:\/\/greatscottgadgets.com\/hackrf\/) devices connected to host notebook PC.\" width=\"1280\" height=\"960\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/31a\/930\/bb1\/31a930bb11eba4edc7e0ea8672138ddf.png\"\/><\/p>\n<div><figcaption>Figure 0. Experimental setup. Two HackRF (<a href=\"https:\/\/greatscottgadgets.com\/hackrf\/\" rel=\"noopener noreferrer nofollow\">https:\/\/greatscottgadgets.com\/hackrf\/<\/a>) devices connected to host notebook PC.<\/figcaption><\/div>\n<\/figure>\n<figure class=\"bordered full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/dbb\/abf\/0bd\/dbbabf0bdeab6ef49b5d0bcf7ca50809.png\" alt=\"Figure 1. GNU radio project gr-ieee802-11 changed to echo configuration.  \" title=\"Figure 1. GNU radio project gr-ieee802-11 changed to echo configuration.  \" width=\"1395\" height=\"857\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/dbb\/abf\/0bd\/dbbabf0bdeab6ef49b5d0bcf7ca50809.png\"\/><\/p>\n<div><figcaption>Figure 1. GNU radio project <a href=\"https:\/\/github.com\/bastibl\/gr-ieee802-11\" rel=\"noopener noreferrer nofollow\">gr-ieee802-11<\/a> changed to echo configuration.  <\/figcaption><\/div>\n<\/figure>\n<p>The fraction of messages received is a measure of channel quality, it&#8217;s to be maximized. I took five parameters for optimization, these were: frequency, sensitivity of encoder\/decoder, transmitter&#8217;s IF gain, receiver&#8217;s IF and VGA gains. The importance of optimal gain is generally obvious. Too low gains mean noisy signal, whereas too big gains lead to nonlinear distortions. In what follows we don&#8217;t  care about what IF or VGA means &#8212; let it be just terms for HackRF physical constituents. Frequency allowed is a separate parameter set  by IEEE 802.11, it controls interference with WiFi sources external to the project. From now on these five variables are just floats, bounded withing finite intervals. <\/p>\n<p>Via zmq interface I sent\/received messages to\/from GR project. Although it&#8217;s possible to incorporate Python functions or modules into GR project, I preferred to control the project from external script. This way I managed to send not more than one message per 10ms.  Another limitation of the project was relatively low fraction of messages successfully passing through the channel, it was ~ 3% at best. As a consequence the measurements of the channel quality  were either too noisy or prohibitively time consuming. In some cases (perhaps not exactly this one) optimization can&#8217;t take too long due to temporal drifts, such as variations in external WiFi sources intensities.  To tackle the problem appropriately I resorted to slightly complicated Gaussian processes (GP). Technically I used gpflow Python package for the work, <a href=\"https:\/\/github.com\/GPflow\/GPflow\" rel=\"noopener noreferrer nofollow\">https:\/\/github.com\/GPflow\/GPflow<\/a> .  <\/p>\n<h2>Gaussian Processes optimization<\/h2>\n<p>GP is  a model of an optimized function in parameter space . Scalar channel quality value <img loading=\"lazy\" decoding=\"async\" class=\"formula inline\" source=\"y\" alt=\"y\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/8ae\/bf6\/708\/8aebf6708e8cde710842f7723ec6142c.svg\" width=\"10\" height=\"16\"\/> is measured at parameter vector <img loading=\"lazy\" decoding=\"async\" class=\"formula inline\" source=\"\\vec{x}\\in X\" alt=\"\\vec{x}\\in X\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/495\/ab0\/361\/495ab03613d1553ce02416ceff2031ee.svg\" width=\"52\" height=\"18\"\/>.     In simplest setting, all channel quality measurements at different points in <img loading=\"lazy\" decoding=\"async\" class=\"formula inline\" source=\"X\" alt=\"X\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/6be\/b6d\/f66\/6beb6df66de6e8c9d5a1169fdcbd600a.svg\" width=\"17\" height=\"17\"\/> are organized into single vector  <img loading=\"lazy\" decoding=\"async\" class=\"formula inline\" source=\"\\vec{Y}\" alt=\"\\vec{Y}\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/127\/b80\/09f\/127b8009f3d547a90776eb47a3276893.svg\" width=\"15\" height=\"21\"\/> distributed as multivariate Gaussian. It&#8217;s  covariance matrix comprises distance dependent term <img loading=\"lazy\" decoding=\"async\" class=\"formula inline\" source=\"K(\\vec{x_1},\\vec{x_2}) = K(||\\vec{x_1}-\\vec{x_2}|||)\" alt=\"K(\\vec{x_1},\\vec{x_2}) = K(||\\vec{x_1}-\\vec{x_2}|||)\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/52e\/a93\/b08\/52ea93b084058ba38cb5b78e66dc635f.svg\" width=\"232\" height=\"28\"\/>  plus constant diagonal  term <img loading=\"lazy\" decoding=\"async\" class=\"formula inline\" source=\"\\Sigma\" alt=\"\\Sigma\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/5fd\/095\/1e3\/5fd0951e391631bf362a6cb77931ba70.svg\" width=\"14\" height=\"17\"\/>.  It practically means that our  measurements are noisy at every single point <img loading=\"lazy\" decoding=\"async\" class=\"formula inline\" source=\"\\vec{x}\" alt=\"\\vec{x}\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/acf\/8cd\/a21\/acf8cda21b088012ea7219ab4d3e31eb.svg\" width=\"11\" height=\"18\"\/>, values of measurements at neighboring  <img loading=\"lazy\" decoding=\"async\" class=\"formula inline\" source=\"\\vec{x}\" alt=\"\\vec{x}\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/a30\/c3d\/c87\/a30c3dc877715d41cfe19a73c62f91dc.svg\" width=\"11\" height=\"18\"\/>-points being statistically dependent. With covariance matrix known, and given some measurements of <img loading=\"lazy\" decoding=\"async\" class=\"formula inline\" source=\"y\" alt=\"y\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/c88\/ece\/586\/c88ece58644e46db94b167f2d2eb70eb.svg\" width=\"10\" height=\"16\"\/> already taken  we could tell the values at  unknown points, with some uncertainty. To predict anything useful, a GP model should be initialized first, i.e. we need to feed it some valuable measured points to estimate covariance matrix. Thus initially parameter space is sampled randomly, until we find a few useful points (we get there non-zero channel quality). To be more certain, vanilla squared exponential kernel was used, <img loading=\"lazy\" decoding=\"async\" class=\"formula inline\" source=\"K(r) = A*\\exp(-\\frac{r^2}{\\lambda^2})\" alt=\"K(r) = A*\\exp(-\\frac{r^2}{\\lambda^2})\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/3eb\/307\/893\/3eb307893c5b28e3c9f1a04115743b33.svg\" width=\"189\" height=\"47\"\/>, thus we&#8217;ve got three learnable parameters: <img loading=\"lazy\" decoding=\"async\" class=\"formula inline\" source=\"\\Sigma\" alt=\"\\Sigma\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/892\/b82\/e5e\/892b82e5e776c957d849847681099072.svg\" width=\"14\" height=\"17\"\/>,  <img loading=\"lazy\" decoding=\"async\" class=\"formula inline\" source=\"A\" alt=\"A\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/842\/0c9\/332\/8420c933231c70ba0779bb11c6e36150.svg\" width=\"15\" height=\"18\"\/>, <img loading=\"lazy\" decoding=\"async\" class=\"formula inline\" source=\"\\lambda\" alt=\"\\lambda\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/2d5\/7a3\/e95\/2d57a3e95a475b8c84ea11fc32b2b611.svg\" width=\"11\" height=\"17\"\/>. <\/p>\n<p>Now suppose we&#8217;ve got GP model initialized. To predict values at new points in <img loading=\"lazy\" decoding=\"async\" class=\"formula inline\" source=\"X\" alt=\"X\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/38e\/737\/3a8\/38e7373a89486357e79e50330624d61b.svg\" width=\"17\" height=\"17\"\/>, posterior distribution is derived with Bayes formula from Gaussian distribution. Luckily it&#8217;s also Gaussian with mean and variance, both dependent on previous points sampled. In parameter space <img loading=\"lazy\" decoding=\"async\" class=\"formula inline\" source=\"X\" alt=\"X\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/1d2\/c72\/84c\/1d2c7284c0b5f8067a14599f9d8f9479.svg\" width=\"17\" height=\"17\"\/> the variance (uncertainty) falls close to measured  <img loading=\"lazy\" decoding=\"async\" class=\"formula inline\" source=\"x\" alt=\"x\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/040\/470\/92f\/04047092f8e48876edc59cb085193ea7.svg\" width=\"11\" height=\"12\"\/>values and rises aside, the mean varies on the distance scale of  <img loading=\"lazy\" decoding=\"async\" class=\"formula inline\" source=\"\\lambda\" alt=\"\\lambda\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/32d\/7cc\/928\/32d7cc928e6a13e3071b12998ab199f3.svg\" width=\"11\" height=\"17\"\/>.  Fig.2 exemplifies posterior distribution in the case of one-dimensional parameter space.  <\/p>\n<figure class=\"bordered\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/866\/dad\/619\/866dad6193c7d966404109b58889990a.png\" alt=\"Figure 2. Posterior distribution of GP for 1D parameter space. Crosses mark points with  measured values. Shaded areas represent uncertainty of values. Possible (of substantial probability) GP realizations are drawn with colored line within uncertainty area. The image was borrowed from http:\/\/gaussianprocess.org\/gpml\/chapters\/RW2.pdf\" title=\"Figure 2. Posterior distribution of GP for 1D parameter space. Crosses mark points with  measured values. Shaded areas represent uncertainty of values. Possible (of substantial probability) GP realizations are drawn with colored line within uncertainty area. The image was borrowed from http:\/\/gaussianprocess.org\/gpml\/chapters\/RW2.pdf\" width=\"458\" height=\"364\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/866\/dad\/619\/866dad6193c7d966404109b58889990a.png\"\/><\/p>\n<div><figcaption>Figure 2. Posterior distribution of GP for 1D parameter space. Crosses mark points with  measured values. Shaded areas represent uncertainty of values. Possible (of substantial probability) GP realizations are drawn with colored line within uncertainty area. The image was borrowed from <a href=\"http:\/\/gaussianprocess.org\/gpml\/chapters\/RW2.pdf\" rel=\"noopener noreferrer nofollow\">http:\/\/gaussianprocess.org\/gpml\/chapters\/RW2.pdf<\/a><\/figcaption><\/div>\n<\/figure>\n<p>Given posterior distribution one might choose what <img loading=\"lazy\" decoding=\"async\" class=\"formula inline\" source=\"\\vec{x} \" alt=\"\\vec{x} \" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/931\/bd7\/0a6\/931bd70a656ea91efac84df7e0bc13e9.svg\" width=\"11\" height=\"18\"\/> should be tried next. There&#8217;s a bunch of strategies here, and it happened for the problem in case that &#8216;conservative&#8217; criterion is suitable, i.e. we took the value with largest <img loading=\"lazy\" decoding=\"async\" class=\"formula inline\" source=\"\\mu(\\vec{x}) - \\sigma(\\vec{x})\" alt=\"\\mu(\\vec{x}) - \\sigma(\\vec{x})\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/629\/45c\/cb7\/62945ccb70e50020cce5090a4cf03e83.svg\" width=\"100\" height=\"22\"\/>. In other words, point with largest worst case value is preferred. After getting <img loading=\"lazy\" decoding=\"async\" class=\"formula inline\" source=\"y\" alt=\"y\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/97e\/3b3\/90c\/97e3b390cdd94f8b3ce0473b66b7ff94.svg\" width=\"10\" height=\"16\"\/>at new point <img loading=\"lazy\" decoding=\"async\" class=\"formula inline\" source=\"\\vec{x} \" alt=\"\\vec{x} \" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/b7f\/22a\/e6d\/b7f22ae6d1ea28a1611194a50abfcce6.svg\" width=\"11\" height=\"18\"\/>the GP model is fit again and the process repeats, until we&#8217;re pretty sure about uncertainties all over the parameter space <img loading=\"lazy\" decoding=\"async\" class=\"formula inline\" source=\"X\" alt=\"X\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/2b1\/b62\/ba9\/2b1b62ba9bb985c45546649a29f8adcb.svg\" width=\"17\" height=\"17\"\/>. For further details on GP see a great resource  <a href=\"http:\/\/gaussianprocess.org\/\" rel=\"noopener noreferrer nofollow\">http:\/\/gaussianprocess.org\/<\/a>,  particularly a brilliant book <a href=\"http:\/\/gaussianprocess.org\/gpml\/\" rel=\"noopener noreferrer nofollow\">http:\/\/gaussianprocess.org\/gpml\/<\/a>). <\/p>\n<h2>Results<\/h2>\n<p>Several complications happened in the course of project development, they should be noted.<\/p>\n<ol>\n<li>\n<p>Frequency was excluded from search space. Although <a href=\"https:\/\/github.com\/bastibl\/gr-ieee802-11\" rel=\"noopener noreferrer nofollow\">gr-ieee802-11<\/a> implementation allows frequency to be changed continuously, channel qualilty degrades very quickly away from a discrete comb of values set by 802.11 standard. The comb structure complicates parameter space and needs a specific approach, e.g. GP kernel might need separate length scale for frequency.<\/p>\n<\/li>\n<li>\n<p>GP process in vanilla form  assumes Gaussian with  constant zero mean. To improve model quality it&#8217;s profitable to subtract the mean from values being optimized. Also, scaling of input space to unit intervals over each variable is necessary for GP optimization (otherwise squared exponential kernel has vanishing gradients).  <\/p>\n<\/li>\n<li>\n<p>The noises observed aren&#8217;t exactly Gaussian distributed, especially for quick channel measurements. It&#8217;s seen even from the fact that they are integer, which seems important at values ~1.  The filtering of ~1 and zero values gave poor results. To learn it&#8217;s parameters correctly GP needs to see zeros and ~ones as well.<\/p>\n<\/li>\n<\/ol>\n<p>Here is an example of optimization sequence, Fig.3. First <img loading=\"lazy\" decoding=\"async\" class=\"formula inline\" source=\"x\" alt=\"x\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/1b3\/303\/f5e\/1b3303f5e4da73ee8efa134a630f87b2.svg\" width=\"11\" height=\"12\"\/>-points were taken randomly until 5 points with non-zero channel qualities appeared.  Last &#8230;  points were taken via model conservative predictions and show considerable improvements over the random search. <\/p>\n<figure class=\"bordered\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/0bd\/a97\/800\/0bda97800e064b60242447c6afdfa455.png\" alt=\"Figure 3. Plot of channel quality (quantity of messages echoed out of 1e03 sent) vs. search step. Crosses label the points of random search stage, it continued until 5 points with non-zero values were accumulated.Circles denote points derived from GP model search.    \" title=\"Figure 3. Plot of channel quality (quantity of messages echoed out of 1e03 sent) vs. search step. Crosses label the points of random search stage, it continued until 5 points with non-zero values were accumulated.Circles denote points derived from GP model search.    \" width=\"382\" height=\"262\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/0bd\/a97\/800\/0bda97800e064b60242447c6afdfa455.png\"\/><\/p>\n<div><figcaption>Figure 3. Plot of channel quality (quantity of messages echoed out of 1e03 sent) vs. search step. Crosses label the points of random search stage, it continued until 5 points with non-zero values were accumulated.Circles denote points derived from GP model search.    <\/figcaption><\/div>\n<\/figure>\n<p>It&#8217;s interesting to analyze the convergence of 20 last points prescribed by GP model, in Fig. 4. It looks like the points oscillate due to noises in channel quality measurements. <\/p>\n<figure class=\"bordered\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/b00\/005\/ae2\/b00005ae2237168207700585b8d25de6.png\" alt=\"Figure 4. Normalized distance of points in GP guided search to the final point of the search. Normalization maps coordinates to [-1,1] intervals.\" title=\"Figure 4. Normalized distance of points in GP guided search to the final point of the search. Normalization maps coordinates to [-1,1] intervals.\" width=\"386\" height=\"263\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/b00\/005\/ae2\/b00005ae2237168207700585b8d25de6.png\"\/><\/p>\n<div><figcaption>Figure 4. Normalized distance of points in GP guided search to the final point of the search. Normalization maps coordinates to [-1,1] intervals.<\/figcaption><\/div>\n<\/figure>\n<h3>Conclusions<\/h3>\n<p>An approach for internals-agnostic GNU-radio project optimization was tried and gave some positive results.   It&#8217;s applicability to arbitrary project is out of question at the time, as difficulty with frequency optimization demonstrates. GP apparatus seems to be a promising tool for noisy &#8216;little&#8217; data, but it requires careful adjustments of kernel and sequential search strategy. <\/p>\n<\/p>\n<\/div>\n<\/div>\n<\/div>\n<p><!----><!----><\/div>\n<p><!----><!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/726248\/\"> https:\/\/habr.com\/ru\/articles\/726248\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<h2>What this all is about<\/h2>\n<p>In this post I&#8217;ll share my experience in adjustment of  WiFi physical channel. The channel was  implemented on a software defined radio (SDR) platform. WiFi looks like a very complicated thing standardized over hundreds of pages. Could a non-expert with PC and a couple of 100$ devices somehow improve it? <\/p>\n<p>I tried to answer the question experimentally. Gaussian processes were engaged to process noisy and time-consuming channel quality measurements. The work results could be used to finely adjust WiFi channel quality. Project code is available at <a href=\"https:\/\/github.com\/KVasya\/AdjustableWiFi\/tree\/gpflow\" rel=\"noopener noreferrer nofollow\">https:\/\/github.com\/KVasya\/AdjustableWiFi\/tree\/gpflow<\/a> .<\/p>\n<h2>Software and hardware involved<\/h2>\n<p>My experiments were based on GNU radio (GR, <a href=\"https:\/\/www.gnuradio.org\/\" rel=\"noopener noreferrer nofollow\">https:\/\/www.gnuradio.org\/<\/a>) implementation of IEEE 802.11 protocol (aka WiFi, <a href=\"https:\/\/github.com\/bastibl\/gr-ieee802-11\" rel=\"noopener noreferrer nofollow\">https:\/\/github.com\/bastibl\/gr-ieee802-11<\/a> by Bastibl). GR enables you to configure a relatively cheap  radio device for WiFi signals. The <a href=\"https:\/\/github.com\/bastibl\/gr-ieee802-11\" rel=\"noopener noreferrer nofollow\">gr-ieee802-11<\/a> implementation in principle reveals all the internal stages of WiFi signal treatment. If we wanted to optimize it, a decent way would be to go deep into the project and see what&#8217;s going on with the signal. A different way is to consider WiFi implementation as a black box and optimize it&#8217;s performance by trying many different project parameter values. This way one actually works with a project facing it for the first time.   My intention was to find a mathematical framework for such a triage of complicated GR projects. If useful, such a functionality could be  wrapped in a standard GR block. <\/p>\n<p>I took 2 HackRF  devices (one for transmissions and one for reception, Fig. 0) and changed <a href=\"https:\/\/github.com\/bastibl\/gr-ieee802-11\" rel=\"noopener noreferrer nofollow\">gr-ieee802-11<\/a> into echo configuration: a short text message is encoded into physical signal, sent through transmitting device, then it&#8217;s caught by receiving device, and then decoded back into text (GNU radio project is shown in Fig. 1). The devices operated in 2.4GHz WiFi frequency range.<\/p>\n<figure class=\"bordered full-width\">\n<div><figcaption>Figure 0. Experimental setup. Two HackRF (<a href=\"https:\/\/greatscottgadgets.com\/hackrf\/\" rel=\"noopener noreferrer nofollow\">https:\/\/greatscottgadgets.com\/hackrf\/<\/a>) devices connected to host notebook PC.<\/figcaption><\/div>\n<\/figure>\n<figure class=\"bordered full-width\">\n<div><figcaption>Figure 1. GNU radio project <a href=\"https:\/\/github.com\/bastibl\/gr-ieee802-11\" rel=\"noopener noreferrer nofollow\">gr-ieee802-11<\/a> changed to echo configuration.  <\/figcaption><\/div>\n<\/figure>\n<p>The fraction of messages received is a measure of channel quality, it&#8217;s to be maximized. I took five parameters for optimization, these were: frequency, sensitivity of encoder\/decoder, transmitter&#8217;s IF gain, receiver&#8217;s IF and VGA gains. The importance of optimal gain is generally obvious. Too low gains mean noisy signal, whereas too big gains lead to nonlinear distortions. In what follows we don&#8217;t  care about what IF or VGA means &#8212; let it be just terms for HackRF physical constituents. Frequency allowed is a separate parameter set  by IEEE 802.11, it controls interference with WiFi sources external to the project. From now on these five variables are just floats, bounded withing finite intervals. <\/p>\n<p>Via zmq interface I sent\/received messages to\/from GR project. Although it&#8217;s possible to incorporate Python functions or modules into GR project, I preferred to control the project from external script. This way I managed to send not more than one message per 10ms.  Another limitation of the project was relatively low fraction of messages successfully passing through the channel, it was ~ 3% at best. As a consequence the measurements of the channel quality  were either too noisy or prohibitively time consuming. In some cases (perhaps not exactly this one) optimization can&#8217;t take too long due to temporal drifts, such as variations in external WiFi sources intensities.  To tackle the problem appropriately I resorted to slightly complicated Gaussian processes (GP). Technically I used gpflow Python package for the work, <a href=\"https:\/\/github.com\/GPflow\/GPflow\" rel=\"noopener noreferrer nofollow\">https:\/\/github.com\/GPflow\/GPflow<\/a> .  <\/p>\n<h2>Gaussian Processes optimization<\/h2>\n<p>GP is  a model of an optimized function in parameter space . Scalar channel quality value  is measured at parameter vector .     In simplest setting, all channel quality measurements at different points in  are organized into single vector   distributed as multivariate Gaussian. It&#8217;s  covariance matrix comprises distance dependent term   plus constant diagonal  term .  It practically means that our  measurements are noisy at every single point , values of measurements at neighboring  -points being statistically dependent. With covariance matrix known, and given some measurements of  already taken  we could tell the values at  unknown points, with some uncertainty. To predict anything useful, a GP model should be initialized first, i.e. we need to feed it some valuable measured points to estimate covariance matrix. Thus initially parameter space is sampled randomly, until we find a few useful points (we get there non-zero channel quality). To be more certain, vanilla squared exponential kernel was used, , thus we&#8217;ve got three learnable parameters: ,  , . <\/p>\n<p>Now suppose we&#8217;ve got GP model initialized. To predict values at new points in , posterior distribution is derived with Bayes formula from Gaussian distribution. Luckily it&#8217;s also Gaussian with mean and variance, both dependent on previous points sampled. In parameter space  the variance (uncertainty) falls close to measured  values and rises aside, the mean varies on the distance scale of  .  Fig.2 exemplifies posterior distribution in the case of one-dimensional parameter space.  <\/p>\n<figure class=\"bordered\">\n<div><figcaption>Figure 2. Posterior distribution of GP for 1D parameter space. Crosses mark points with  measured values. Shaded areas represent uncertainty of values. Possible (of substantial probability) GP realizations are drawn with colored line within uncertainty area. The image was borrowed from <a href=\"http:\/\/gaussianprocess.org\/gpml\/chapters\/RW2.pdf\" rel=\"noopener noreferrer nofollow\">http:\/\/gaussianprocess.org\/gpml\/chapters\/RW2.pdf<\/a><\/figcaption><\/div>\n<\/figure>\n<p>Given posterior distribution one might choose what  should be tried next. There&#8217;s a bunch of strategies here, and it happened for the problem in case that &#8216;conservative&#8217; criterion is suitable, i.e. we took the value with largest . In other words, point with largest worst case value is preferred. After getting at new point the GP model is fit again and the process repeats, until we&#8217;re pretty sure about uncertainties all over the parameter space . For further details on GP see a great resource  <a href=\"http:\/\/gaussianprocess.org\/\" rel=\"noopener noreferrer nofollow\">http:\/\/gaussianprocess.org\/<\/a>,  particularly a brilliant book <a href=\"http:\/\/gaussianprocess.org\/gpml\/\" rel=\"noopener noreferrer nofollow\">http:\/\/gaussianprocess.org\/gpml\/<\/a>). <\/p>\n<h2>Results<\/h2>\n<p>Several complications happened in the course of project development, they should be noted.<\/p>\n<ol>\n<li>\n<p>Frequency was excluded from search space. Although <a href=\"https:\/\/github.com\/bastibl\/gr-ieee802-11\" rel=\"noopener noreferrer nofollow\">gr-ieee802-11<\/a> implementation allows frequency to be changed continuously, channel qualilty degrades very quickly away from a discrete comb of values set by 802.11 standard. The comb structure complicates parameter space and needs a specific approach, e.g. GP kernel might need separate length scale for frequency.<\/p>\n<\/li>\n<li>\n<p>GP process in vanilla form  assumes Gaussian with  constant zero mean. To improve model quality it&#8217;s profitable to subtract the mean from values being optimized. Also, scaling of input space to unit intervals over each variable is necessary for GP optimization (otherwise squared exponential kernel has vanishing gradients).  <\/p>\n<\/li>\n<li>\n<p>The noises observed aren&#8217;t exactly Gaussian distributed, especially for quick channel measurements. It&#8217;s seen even from the fact that they are integer, which seems important at values ~1.  The filtering of ~1 and zero values gave poor results. To learn it&#8217;s parameters correctly GP needs to see zeros and ~ones as well.<\/p>\n<\/li>\n<\/ol>\n<p>Here is an example of optimization sequence, Fig.3. First -points were taken randomly until 5 points with non-zero channel qualities appeared.  Last &#8230;  points were taken via model conservative predictions and show considerable improvements over the random search. <\/p>\n<figure class=\"bordered\">\n<div><figcaption>Figure 3. Plot of channel quality (quantity of messages echoed out of 1e03 sent) vs. search step. Crosses label the points of random search stage, it continued until 5 points with non-zero values were accumulated.Circles denote points derived from GP model search.    <\/figcaption><\/div>\n<\/figure>\n<p>It&#8217;s interesting to analyze the convergence of 20 last points prescribed by GP model, in Fig. 4. It looks like the points oscillate due to noises in channel quality measurements. <\/p>\n<figure class=\"bordered\">\n<div><figcaption>Figure 4. Normalized distance of points in GP guided search to the final point of the search. Normalization maps coordinates to [-1,1] intervals.<\/figcaption><\/div>\n<\/figure>\n<h3>Conclusions<\/h3>\n<p>An approach for internals-agnostic GNU-radio project optimization was tried and gave some positive results.   It&#8217;s applicability to arbitrary project is out of question at the time, as difficulty with frequency optimization demonstrates. GP apparatus seems to be a promising tool for noisy &#8216;little&#8217; data, but it requires careful adjustments of kernel and sequential search strategy. <\/p>\n<\/p>\n<\/div>\n<\/div>\n<\/div>\n<p><!----><!----><\/div>\n<p><!----><!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/726248\/\"> https:\/\/habr.com\/ru\/articles\/726248\/<\/a><br \/><\/br><\/br><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-404804","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/404804","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=404804"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/404804\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=404804"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=404804"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=404804"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}