tag:blogger.com,1999:blog-44126892762794525012021-07-27T20:37:06.607+02:00Data Analytics For All presenting my ideas and views and also I’m ready to take on a new challenge !
Bogdan Lobodzinskihttp://www.blogger.com/profile/09289422592105592639noreply@blogger.comBlogger8125tag:blogger.com,1999:blog-4412689276279452501.post-57552531037351882002021-07-15T12:58:00.004+02:002021-07-15T13:40:10.999+02:00Global Real Estate market: a non-expert view<!-- MathJax usage example --><script type="text/x-mathjax-config">MathJax.Hub.Config({tex2jax: {inlineMath: [['$','$'], ['\\(','\\)']]}});</script><script type="text/x-mathjax-config">MathJax.Hub.Config({TeX: { equationNumbers: { autoNumber: "AMS" }}});</script><script src="https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML" type="text/javascript"> </script><script src="https://cdn.rawgit.com/google/code-prettify/master/loader/run_prettify.js"></script> <div class="separator" style="clear: both;"><a href="https://1.bp.blogspot.com/-U5DtLrsognE/YPAZopd8WkI/AAAAAAAAAUQ/8M0WrRaoDesPfRtycVwVmjybdsZqkNV_QCLcBGAsYHQ/s790/orchestra.webp" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="320" data-original-height="310" data-original-width="790" src="https://1.bp.blogspot.com/-U5DtLrsognE/YPAZopd8WkI/AAAAAAAAAUQ/8M0WrRaoDesPfRtycVwVmjybdsZqkNV_QCLcBGAsYHQ/s320/orchestra.webp"/></a></div> <b>About:</b><br />Most analyses of real estate prices compare their behavior over time with other economic indicators, but this is done for a specific country or independently for a group of countries. This text proposes a comparison of real estate prices between different countries by calculating the correlation between them. <br /><br /> <b>Data:</b><br />I came across some data on real estate prices (https://data.world/finance/international-house-price-database). This data contains values of 4 quantities (with short descriptions found in wikipedia and other sources): <ol><li> the house price index (HPI): <br />measures the price changes of residential housing as a percentage change from some specific start date (starting in 1975).</li><li> the house price index expressed in real terms (RHPI):<br />the deflated house price index (or real house price index) is the ratio between the house price index (HPI)</li><li> the personal disposable income index (PDI):<br />measures the after-tax income of persons and nonprofit corporations.</li>It is calculated by subtracting personal tax and nontax payments from personal income. <li> the personal disposable income expressed in real terms index (RPDI) :<br />the deflated PDI. </li></ol> <br /><br /> <b>Analysis:</b><br /> As input we have time series with specified quantity $Q$ (HPI, RHPI, PDI or RPDI) for N (N=24) countries ( 'Australia', 'Belgium', 'Canada', 'Switzerland', 'Germany', 'Denmark', 'Spain', 'Finland', 'France', 'UK', 'Ireland', 'Italy', 'Japan', 'S. Korea', 'Luxembourg', 'Netherlands', 'Norway', 'New Zealand', 'Sweden', 'US', 'S. Africa', 'Croatia', 'Israel', 'Slovenia'). In order to calculate correlations between countries I do the following calculations: <ol><li> for a given quantity $Q$ I normalize all data independently to the range [0,1],</li><li> I determine the two-site correlation function for each timestamp $t$ \begin{equation} \label{1} Corr_{country, another\_country} \left(t \right) = Q_{country}\left(t \right) Q_{another\_country}\left(t \right) \end{equation} which is used finaly, for calculation of the global correlation for each country: \begin{equation} \label{2} C_{country}\left(t \right) = \frac{\sum_{another\_country=1}^{N} Corr_{country, another\_country} \left(t \right) }{N} \end{equation} </li></ol><br /> The dynamics of the thus calculated correlation function $C_{country}\left(t \right)$ for the quantity $Q=$RHPI and for all countries is shown in Figure 1. For the quantity RHPI, the correlations are most apparent. <div class="separator" style="clear: both;"><a href="https://1.bp.blogspot.com/-NCroi4pKjlc/YPAeexW3jDI/AAAAAAAAAUY/cP1sc3JeB1Ik26zLC8szcp1yVPPrEeEawCLcBGAsYHQ/s1436/rhpi.png" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="600" data-original-height="1399" data-original-width="1436" src="https://1.bp.blogspot.com/-NCroi4pKjlc/YPAeexW3jDI/AAAAAAAAAUY/cP1sc3JeB1Ik26zLC8szcp1yVPPrEeEawCLcBGAsYHQ/s600/rhpi.png"/></a></div> The financial crisis of 2008 is very well visible in this figure (the yellow cylinder between 2007 and 2008). <br /><br /> <b>A couple of observations for the time period 2007-2008:</b><br />The longest increase of the value of RHPI is seen for the US, lasting since about 1995. Other countries behave in a weakly correlated way during this period. A strong correlation between countries starts to be visible from about 2005 and quickly increases until the crash around 2007-2008. It looks as if most countries joined the global real estate market at the same time (around 2005) and at a given signal decided to crash - <i>"ready, steady, crash!"</i>. The market seems to be too well orchestrated. I know that some people will say that this is a normal behavior because it is a global market, all markets are interconnected, etc. However, please note that it is hard to see any trace of the dot-com crisis of 2000-2003 (dot-com bubble) in this picture. Another comment on the picture concerns the number of countries participating in the crash. There are some countries excluded (Japan, S. Korea, Israel) or weakly participating in the process (Australia, Canada, Switzerland, Germany, New Zealand, Sweden, Croatia). Altogether, 13 countries out of 24 are affected by the crash. <br /><br /> <b>Observations for the time period 2008-now:</b><br />The first observation is that more countries are now correlated (and not because of COVID). Still outside the correlated market are Japan, S. Korea and Croatia. Spain, Italy are not correlated (accident at work?). <br /><br /> <b>Summary:</b><br />the management of the real estate market is becoming more and more concise (only one player? ): currently 19 countries out of 24 (crisis 2008: 13 countries).<br /><b><i>Question: when will this player decide to make another crash?</i></b><br /><br /> If anyone has knowledge of more data I would be grateful for providing it. Bogdan Lobodzinskihttp://www.blogger.com/profile/09289422592105592639noreply@blogger.com0tag:blogger.com,1999:blog-4412689276279452501.post-10006004884018636122021-05-14T15:17:00.002+02:002021-05-14T21:50:35.532+02:00Semantic Search: Too many or too few matching pairs ? Dynamically determined selection threshold for matched query pairs<!-- MathJax usage example --><script type="text/x-mathjax-config">MathJax.Hub.Config({tex2jax: {inlineMath: [['$','$'], ['\\(','\\)']]}});</script><script type="text/x-mathjax-config">MathJax.Hub.Config({TeX: { equationNumbers: { autoNumber: "AMS" }}});</script><script src="https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML" type="text/javascript"> </script><script src="https://cdn.rawgit.com/google/code-prettify/master/loader/run_prettify.js"></script> In my recent projects on applying Natural language processing (NLP) methods, a large part is based or contains parts based on <i><b>semantic search</i></b>. In a nutshell, we have certain queries (phrases or sentences) on one side and a set of other texts on the other side and our goal is to find the best matching texts to our query. Simply writing, we need to perform semantic search on our data set. <br /> <br />For those who are less familiar with semantic search, let me define the term as: <br /><i><b>a kind of lexical comparison of two texts with dominant part of understanding the content of words and phrases, and relations between words or phrases in queries being compared. </i></b><br /> <br /> While working with semantic search, I encountered a problem with defining the acceptance threshold for my findings. This problem becomes significant when the texts being compared are of significantly different lengths and/or contain significantly different degrees of content. In other words, the problem becomes serious when we deal with the so-called asymmetric semantic search <a href="https://www.sbert.net/examples/applications/semantic-search/README.html#symmetric-vs-asymmetric-semantic-search"><b>https://www.sbert.net/examples/applications/semantic-search/README.html#symmetric-vs-asymmetric-semantic-search</b></a>.<br /> <br /> In the following, I would like to share a method which allows to dynamically determine the acceptance threshold of found pairs of matched entries. This method may determine the final solution or be a prelude to a more modified version. The project code is available on my Github account <a href="https://github.com/Lobodzinski/Semantic_Search__dynamical_estimation_of_the_cut_of_for_selected_matches"><b>"https://github.com/Lobodzinski/Semantic_Search__dynamical_estimation_of_the_cut_of_for_selected_matches"</b></a>.<br /> <br /> Let's start describing the method. <ul><li> <b>The data:</b><br />As an experiment I will use reuters data, known as reuters-21578 (https://paperswithcode.com/dataset/reuters-21578). While searching for an answer to our query, we should try to be as precise as possible in formulating the questions. However, sometimes it is not possible. For the purpose of this mini-project, let's formulate <b>our queries</b> in a general form.<br /> <i>'Behavior of the precious metals market'</i>,<br /><i>'What is the situation in metal mines'</i>,<br /><i>'Should fuel prices expect to rise ?'</i>,<br /><i>'Will food prices rise in the near future ?'</i>,<br /><i>'I am looking for information about food crops.'</i>,<br /><i>'Information on the shipbuilding industry'</i><br /> <li> <b>Generation of matched pairs between the queries and the Reuter's texts:</b><br /> Our goal is to perform a semantic search. First, we need to generate matching text pairs. In the following I will use the code that is part of the sentence-transformers package <a href="https://github.com/UKPLab/sentence-transformers/tree/master/examples/applications/semantic-search"><b>"https://github.com/UKPLab/sentence-transformers/tree/master/examples/applications/semantic-search"</b></a>.<br /> <li> <b>Similarities and the threshold calculation:</b><br /> Having calculated the similarity values, we can move to the main point - choosing the similarity threshold. First, let's look at the similarity plot in the test function for a fixed query (<i><b>'What is the situation in metal mines ?'</b></i>) <div class="separator" style="clear: both;"><a href="https://1.bp.blogspot.com/-5ZJFuj86BBE/YJ5qV8thTkI/AAAAAAAAASI/nhkRTFHQ9hsWktCrU-d42nvjhdJZXMzJQCLcBGAsYHQ/s0/fig1.png" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" data-original-height="898" data-original-width="747" src="https://1.bp.blogspot.com/-5ZJFuj86BBE/YJ5qV8thTkI/AAAAAAAAASI/nhkRTFHQ9hsWktCrU-d42nvjhdJZXMzJQCLcBGAsYHQ/s0/fig1.png"/></a></div> It is obvious that not all matches shown in the Figure are good (acceptable). So how to choose the threshold value of similarity ? <br />The proposed method is fully heuristic and is based on the calculation of the <i><b>elbow point</b></i> of the curve of the similarity as a function of the matched text. If we take a look at the examined functional relationship, we can see that this curve (almost always) has an elbow point beyond which the similarity between the found texts and our query changes very slowly. To calculate the "cut off" point (elbow point) I used the KneeLocator package (<a href="https://pypi.org/project/kneed/"><b>"https://pypi.org/project/kneed/"</b></a>). The function KneeLocator (<a href="https://kneed.readthedocs.io/en/stable/parameters.html#s"><b>"https://kneed.readthedocs.io/en/stable/parameters.html#s"</b></a>) contains a sensitivity parameter <b>S</b> which can be used to better select our elbow point.<br /> The following code and its output shows the details of the calculation and its results. For details, please check <a href="https://github.com/Lobodzinski/Semantic_Search__dynamical_estimation_of_the_cut_of_for_selected_matches"><b>"https://github.com/Lobodzinski/Semantic_Search__dynamical_estimation_of_the_cut_of_for_selected_matches"</b></a>.<br />.<br /><br /> This part, for each query reads all matched sentences gathered from the Reuters data together with calculated similarities. The <b>threshold</b> is calculated by the function <b>KneeLocator</b>, this part is denoteb by bold text in the code below.<br /> <pre class="prettyprint"><code><br /># loop over our list of queries:<br />for query in result_df['query'].unique():<br /><br /> sentences_ = result_df[(result_df['query'] == query)]['sentence'].values<br /> x = []<br /> for y_ in sentences_:<br /> x.append(y_[:60]+'...')<br /> <br /> <b><br /> # similarities between the query and the matched Reuter's texts:<br /> y1 = result_df[(result_df['query'] == query)]['score'].values<br /> <br /> # determne elbow value: <br /> x0 = list(range(len(y1)))<br /> <br /> kn = KneeLocator(x0, y1, S=1., curve='convex', direction='decreasing') <br /> elbow_1 = kn.knee<br /> print ('Elbow point values:\n tekst_id=', elbow_1, \<br /> '; threshold value=',y1[elbow_1])<br /> </b><br /> <br /> </code></pre> Resulting value (the threshold point) is presented on the next Figure : <div class="separator" style="clear: both;"><a href="https://1.bp.blogspot.com/-DIrsp3JrZ7M/YJ5zAsJ3AXI/AAAAAAAAASc/-SvhXmkCw5MEdL9DxoyijcDi8tamfVuOwCLcBGAsYHQ/s0/fig2.png" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" data-original-height="898" data-original-width="747" src="https://1.bp.blogspot.com/-DIrsp3JrZ7M/YJ5zAsJ3AXI/AAAAAAAAASc/-SvhXmkCw5MEdL9DxoyijcDi8tamfVuOwCLcBGAsYHQ/s0/fig2.png"/></a></div><br /> So, for our query (<i><b>'What is the situation in metal mines ?'</b></i>), we found 14 texts in the Reuter's set. Below I have copied the first 3 and last 2 texts from the set of accepted texts (the whole set is too long to present here). The reader can judge for themselves the similarity between the query and the text.<br />For comparison, I have also added the text which is not accepted (15), which is not accepted by this method.<br /> Accepted texts:<br /> <i> 1 <br /> SIX KILLED IN SOUTH AFRICAN GOLD MINE ACCIDENT Six black miners have been killed and two injured in a rock fall three km underground at a South African gold mine, the owners said on Sunday. lt Rand Mines Properties Ltd>, one of South Africa s big six mining companies, said in a statement that the accident occurred on Saturday morning at the lt East Rand Proprietary Mines Ltd> mine at Boksburg, 25 km east of Johannesburg. A company spokesman could not elaborate on the short statement.<br /> 2 <br /> NORANDA BEGINS SALVAGE OPERATIONS AT MURDOCHVILLE lt Noranda Inc> said it began salvage operations at its Murdochville, Quebec, mine, where a fire last week killed one miner and caused 10 mln dlrs in damage. Another 56 miners were trapped underground for as long as 24 hours before they were brought to safety. Noranda said the cause and full extent of the damage is still unknown but said it does know that the fire destroyed 6,000 feet of conveyor belt. Noranda said work crews have begun securing the ramp leading into the zone where the fire was located. The company said extreme heat from the fire caused severe rock degradation along several ramps and drifts in the mine. Noranda estimated that the securing operation for the zone will not be completed before the end of April. Noranda said the Quebec Health and Safety Commission, the Quebec Provincial Police and Noranda itself are each conducting an investigation into the fire. Production at the mine has been suspended until the investigations are complete. The copper mine and smelter produced 72,000 tons of copper anodes in 1986 and employs 680 people. The smelter continues to operate with available concentrate from stockpiled supplies, Noranda said. Reuter <br /> 3 <br /> NORTHGATE QUEBEC GOLD WORKERS END STRIKE Northgate Exploration Ltd said hourly paid workers at its two Chibougamau, Quebec mines voted on the weekend to accept a new three year contract offer and returned to work today after a one month strike. It said the workers, represented by United Steelworkers of America, would receive a 1.21 dlr an hour pay raise over the life of the new contract and improved benefits. Northgate, which produced 23,400 ounces of gold in first quarter, said that while the strike slowed production, We are still looking forward to a very satisfactory performance. The Chibougamau mines produced 81,500 ounces of gold last year. <br /> ....<br /> 13 <br /> NORANDA BRUNSWICK MINERS VOTE MONDAY ON CONTRACT Noranda Inc said 1,100 unionized workers at its 63 pct owned Brunswick Mining and Smelter Corp lead zinc mine in New Brunswick would start voting Monday on a tentative contract pact. Company official Andre Fortier said We are hopeful that we can settle without any kind of work interruption. Fortier added that Brunswick s estimated 500 unionized smelter workers were currently meeting about a Noranda contract proposal and would probably vote next week. The mine s contract expires July 1 and the smelter s on July 21. The Brunswick mine produced 413,800 tonnes of zinc and 206,000 tonnes of lead last year at a recovery rate of 70.5 pct zinc and 55.6 pct lead. Concentrates produced were 238,000 tonnes of zinc and 81,000 tonnes of lead. <br /> 14 <br /> COMINCO lt CLT> SETS TENTATIVE TALKS ON STRIKE Cominco Ltd said it set tentative talks with three striking union locals that rejected on Saturday a three year contract offer at Cominco s Trail and Kimberley, British Columbia lead zinc operations. The locals, part of United Steelworkers of America, represent 2,600 production and maintenance workers. No date has been set for the talks, the spokesman replied to a query. The spokesman said talks were still ongoing with the two other striking locals, representing 600 office and technical workers. Production at Trail and Kimberley has been shut down since the strike started May 9. Each of the five locals has a separate contract that expired April 30, but the main issues are similar. The Trail smelter produced 240,000 long tons of zinc and 110,000 long tons of lead last year, while the Sullivan mine at Kimberley produced 2.2 mln long tons of ore last year, most for processing at Trail. Revenues from Trail s smelter totaled 356 mln Canadian dlrs in 1986. </i> <br /> <br />Not Accepted texts:<br /><i>15<br />VESSEL LOST IN PACIFIC WAS CARRYING LEAD The 37,635 deadweight tonnes bulk carrier Cumberlande, which sank in the South Pacific last Friday, was carrying a cargo which included lead as well as magnesium ore, a Lloyds Shipping Intelligence spokesman said. He was unable to confirm the tonnages involved. Trade reports circulating the London Metal Exchange said the vessel, en route to New Orleans from Newcastle, New South Wales, had been carrying 10,000 tonnes of lead concentrates. Traders said this pushed lead prices higher in early morning trading as the market is currently sensitive to any fundamental news due to its finely balanced supply demand position and low stocks. Trade sources said that 10,000 tonnes of lead concentrates could convert to around 5,000 tonnes of metal, although this depended on the quality of the concentrates. A loss of this size could cause a gap in the supply pipeline, particularly in North America, they noted. Supplies there have been very tight this year and there is a strike at one major producer, Cominco, and labour talks currently being held at another, Noranda subsidiary Brunswick Mining and Smelting Ltd. <br />16 <br /> LTV lt QLTV> TO NEGOTIATE WITH STEELWORKERS LTV Corp s LTV Steel Corp said it agreed to resume negotiations with the United Steelworkers of America at the local plant levels, to discuss those provisions of its proposal that require local implementation. The local steelworker union narrowly rejected a tentative agreement with the company on May 14, it said. LTV also said it agreed to reopen its offer contained in the tentative agreement reached with the union s negotiating committee as part of a plan to resolve problems through local discussions.<br /> </i> <br /><br />As you can see, the unaccepted texts are not directly related to mining, which is what we are asking about in our query. </ul><br /><br />Thanks for reading, please feel free to comment and ask questions if anything is unclear. Bogdan Lobodzinskihttp://www.blogger.com/profile/09289422592105592639noreply@blogger.com0tag:blogger.com,1999:blog-4412689276279452501.post-16822155957666762262021-04-07T12:22:00.008+02:002021-05-14T21:50:13.052+02:00Weird aspects of ARIMA - how to increase the accuracy of predictions by exogenous data<!-- MathJax usage example --><script type="text/x-mathjax-config">MathJax.Hub.Config({tex2jax: {inlineMath: [['$','$'], ['\\(','\\)']]}});</script><script type="text/x-mathjax-config">MathJax.Hub.Config({TeX: { equationNumbers: { autoNumber: "AMS" }}});</script><script src="https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML" type="text/javascript"> </script> ARIMA models are commonly used to predict time series. Most importantly, if the ARIMA model is properly chosen, the prediction error is often so small that it is a very difficult task to find better predictions using more sophisticated methods. Since this is not a note about an introduction to ARIMA models I replace the typical introduction to the models with this link which describes the method much better: <a href="https://otexts.com/fpp2/"><b>Forecasting: Principles and Practice"</b> (2nd ed)</a> by Rob J Hyndman and George Athanasopoulos (<i>https://otexts.com/fpp2/</i>).<br /> One of the variants of ARIMA models is a version using exogeneous data, to which this note is dedicated.<br /><i><b>It is not widely known that this version of ARIMA models is strongly dependent on the factor by which we multiply the exogeneous data. Generalizing, we can say that the larger the factor, the smaller the prediction error of the model. </b></i><br /><br />To begin with, let us start with a heuristic proof that the factor determining the ratio between the exogeneous data and the target, can influence the prediction error of the algorithm.<br /><br />For simplicity, let us omit the part of the time series description which in ARIMA models is responsible for the differentiable part, i.e. we assume that the parameter $d=0$. In other words, we will use the formulations of the ARMAX model. <br />Then, a given time series X, in ARMAX, can be expressed generally as: \begin{equation} \label{eq1} X_{t}= c + \epsilon_{t} + AR_{t} + MA_{t} + exog_{t} \end{equation} where $c$: constant, $\epsilon_{t}$: white noise, $AR_{t}$: Autoregression part, $MA_{t}$: Moving average part, $exog_{t}$: exogeneous variable(s).<br/> Now, let's define the exogeneous part $exog_{t}$ as: \begin{equation} \label{eq2} exog_{t} = X_{t} \alpha + \gamma_{t} \end{equation} where $\alpha$ is some proportionality factor, $\gamma_{t}$ - white nose. <br/> Therefore, introducing eq. \ref{eq2} to eq. \ref{eq1} we will get: \begin{equation} \label{eq3} X_{t} = c + \epsilon_{t} + AR_{t} + MA_{t} + X_{t} \alpha + \gamma_{t} \end{equation} And after rearranging some terms \begin{equation} \label{eq4} X_{t}\left(1-\alpha\right) = c + \left(\epsilon_{t} + \gamma_{t}\right) + AR_{t} + MA_{t} \end{equation} But the part $AR_{t}$ can be written as $AR_{t} = \sum_{i}^{p} \phi_{i} X_{t-i}$ and similarly the $MA_{t}$ component $MA_{t} = \langle X \rangle + \beta_{t} + \sum_{i}^{q} \theta_{i} \beta_{t-i}$ with: $\beta_{n}$ as a white noise, $ \langle X \rangle $ - the expectation value of the $X$, $\theta_{i}$ - parameters of the model. <br/> With the above in mind, the eq \ref{eq4} becomes : \begin{equation} \label{eq5} X_{t} = \frac{c + \epsilon_{t} + \gamma_{t} + \alpha \langle X \rangle}{1-\alpha} + \sum_{i} \hat{\phi}_{i} X_{t-i} + \langle X \rangle + \hat{\beta}_{t} + \sum_{i} \theta_{i} \hat{\beta}_{t-i} \end{equation} where I introduced notation: $\hat{\beta}_{t-i} = \frac{\beta_{t-i}}{1-\alpha}$, $\hat{\phi}_{i} = \frac{\phi_{i}}{1-\alpha}$ and $\hat{\theta}_{i} = \frac{\theta_{i}}{1-\alpha}$.<br/> Using definitiona of the $AR_{t}$ and $MA_{t}$ we can rewrite eq \ref{eq5} into the final form: \begin{equation} \label{eq6} X_{t} = \frac{c + \epsilon_{t} + \gamma_{t} + \alpha \langle X \rangle}{1-\alpha} + \hat{AR}_{t} + \hat{MA}_{t} \end{equation} where components $\hat{AR}_{t}$ and $\hat{MA}_{t}$ correspond to the definitions $AR_{t}$ and $MA_{t}$ but with $\hat{\phi}$, $\hat{\theta}$ and $\hat{\beta}$ coefficients. <br/> The first component of Equation \ref{eq6} is the most interesting !. <br/>In the case of ARIMA without exogeneous data, the forecasting error is determined by the $\epsilon$ . Now, this error is replaced by the expression \begin{equation} \label{eq7} \epsilon_{t} \longrightarrow \frac{\epsilon_{t} + \gamma_{t}}{1-\alpha} \end{equation} <br/><b>This is how we reached our final conclusions: <ol> <li>use exogenous variables that are highly correlated ($\alpha \approx 1.$) or anti-correlated ($\alpha \approx -1.$) with the target is equivalent to a model without exogenous variables (but with changed model parameters).</li><li>the use of exog data, scaled by the ratio $\frac{exogenous data}{target}$ allows for a significant modification of the final prediction error of the model. </b>The error is now scaled by the factor $\frac{1}{1-\alpha}$. So <ol><li> we have the error explosions for $\left|\alpha\right| \approx 1$,</li><li> for $\left|\alpha\right| < 1 $: error with exog data $>$ error without exogenous variable,</li><li> for $\left|\alpha\right| > 1 $: error with exog data $<$ error without exogenous variable.</li></li></ol></ol> The above derivation was made for the simplified case without the differential term (i.e., when $d,D=0$). I leave it to the readers to generalize the above formalism into a model with a differential parts. <br/><br/><br/> The next step will be a verification of these hypotheses in practice. A practical example of the implementation of the discussed hypothesis is available in the form of a jupyter-notebook script: <a href="https://github.com/Lobodzinski/ARIMA_with_exogenous_data"><b>https://github.com/Lobodzinski/ARIMA_with_exogenous_data</b></a>. <br/>Here, we just present the dependence of the MAPE error as a function of the exog data factor (in the log10 scale). As you can see, by using an appropriate value of the factor we are able to reduce the prediction error by almost half ! The error reaches its minimum value at a factor value of 4000000. Then the error increases. The increasing part after the minimum is reached is not directly visible in the theoretical proof. I will try to explain it in the next part of the article. <br/>All other details are available in the code: <a href="https://github.com/Lobodzinski/ARIMA_with_exogenous_data"><b>https://github.com/Lobodzinski/ARIMA_with_exogenous_data</b></a>. <div class="separator" style="clear: both;"><a href="https://1.bp.blogspot.com/-oV2jjoUnjvg/YG2xVks0fZI/AAAAAAAAARY/Y9rchuLajsMficxxIVRF1xHG_Xc5QHW9gCLcBGAsYHQ/s717/mape.png" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="600" data-original-height="387" data-original-width="717" src="https://1.bp.blogspot.com/-oV2jjoUnjvg/YG2xVks0fZI/AAAAAAAAARY/Y9rchuLajsMficxxIVRF1xHG_Xc5QHW9gCLcBGAsYHQ/s600/mape.png"/></a></div><br/><br/> Thank you for the reading ! Bogdan Lobodzinskihttp://www.blogger.com/profile/09289422592105592639noreply@blogger.com0tag:blogger.com,1999:blog-4412689276279452501.post-15218648749262247382016-06-22T14:50:00.000+02:002021-05-14T21:50:59.637+02:00Sell - buy signals for financial instruments - a multivariate survival analysis approach (in R).<!-- MathJax usage example --><script type="text/x-mathjax-config">MathJax.Hub.Config({tex2jax: {inlineMath: [['$','$'], ['\\(','\\)']]}}); </script> <script src="https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML" type="text/javascript"> </script><script src="https://cdn.rawgit.com/google/code-prettify/master/loader/run_prettify.js"></script> Survival analysis could be understand as a kind of a forecasting method created for studying how long an analyzed subject will exist. In a survival framework we calculate survival probability of a thing at particular points of time. <br />And so, it is a natural choice to use the survival method in forecasting of financial market. Especially, for prediction of future price behaviour of a given financial instance and as a consequence for generating buy-sell signals. Searching for some examples of similar analysis I have found only a single work addressing the subject [1]. From this publication I adopted a definition of a daily revenue - given below. <br /><br />In this note I would like to show how to use the survival analysis method for generation of <b>buy/sell signals</b> for a chosen financial product. As data I use <b>Brent Oil Future</b> options, however the method could be adopted to other instruments as well. <br /><br />The analysis is presented in R language.<br />As an input I use historical data of Brent Oil Future options available on the portal <a href="http://stooq.com/q/d/?s=sc.f&d1=20150101&d2=20160617&c=0">stooq.pl</a>. The data contain several features like <b>Open</b> and <b>Close</b> prices, <b>Volume</b>, highest (<b>High</b>) and lowest (<b>Low</b>) prices and Open Interest (<b>OpenInt</b>). Operating on a <b>daily basis</b>, my goal is to predict whether for the next day we expect increase or decrease of the <b>Close</b> value.<br />Let me begin with preparation of libraries and data engineering. <br /><pre class="prettyprint"><code>set.seed(1)<br />library(ggplot2)<br />library(lubridate)<br />library(readr)<br />library(MASS)<br />library(survival)<br />library(xts)<br />library(rms)<br /><br /># reading the data:<br />myDir <- "/analysis/forecasting/data_stooq.pl/"<br />myFile <- "sc_f_d_2015_2016.csv" <br />input <- NULL<br />input <- read.csv(paste(myDir,myFile,sep=""),header=TRUE)<br /><br />names(input)<br />[1] "Date" "Open" "High" "Low" <br />[5]"Close" "Volume" "OpenInt"<br /></code></pre> In a next step I will introduce new features:<br /><ol><li> $corp = Close - Open$ : it corresponds to the definition of the corp of the candlesticks, <pre class="prettyprint"><code>input$corp <- 0 <br />input$corp <- input$Close - input$Open<br /></code></pre></li><li> Exponential Moving Average - $EMAV$. For this purpose I use functions for calculation of the Volume Weighted Exponential Moving Average (see <a href="http://www.r-bloggers.com/volume-weighted-exponential-moving-average/">volume-weighted-exponential-moving-average</a>) <pre class="prettyprint"><code>VEMA.num <- function(x, volumes, ratio) {<br /> ret <- c()<br /> s <- 0<br /> for(i in 1:length(x)) { <br /> s <- ratio * s + (1-ratio) * x[i] * volumes[i];<br /> ret <- c(ret, s); <br /> }<br /> ret<br />}<br /><br />VEMA.den <- function(volumes, ratio) {<br /> ret <- c()<br /> s <- 0<br /> for(i in 1:length(x)) { <br /> s <- ratio * s + (1-ratio) * volumes[i]; <br /> ret <- c(ret, s); <br /> }<br /> ret<br />}<br /><br />VEMA <- function(x, volumes, n = 10, wilder = F, ratio = NULL, ...)<br />{<br /> x <- try.xts(x, error = as.matrix)<br /> if (n < 1 || n > NROW(x))<br /> stop("Invalid 'n'")<br /> if (any(nNonNA <- n > colSums(!is.na(x))))<br /> stop("n > number of non-NA values in column(s) ", <br /> paste(which(nNonNA),collapse = ", "))<br /> x.na <- xts:::naCheck(x, n)<br /> if (missing(n) & !missing(ratio)) {<br /> n <- trunc(2/ratio - 1)<br /> } <br /> if (is.null(ratio)) {<br /> if (wilder)<br /> ratio <- 1/n<br /> else ratio <- 2/(n + 1)<br /> }<br /> <br /> foo <- cbind(x[,1], volumes, VEMA.num(as.numeric(x[,1]), volumes, ratio), <br /> VEMA.den(volumes, ratio))<br /> (foo[,3] / foo[,4]) -> ma<br /> <br /> ma <- reclass(ma, x)<br /> if (!is.null(dim(ma))) {<br /> colnames(ma) <- paste(colnames(x), "VEMA", n, sep = ".")<br /> }<br /> return(ma)<br />}<br /><br />x <- ts(input$Close)<br />input$EMAV <- 0<br />Vol <- rep(1, length(input[,1])) <br />input$EMAV <- VEMA(input$Close, Vol,ratio=0.95)<br />plot(input$Close,type="l");lines(input$EMAV,col="red")<br /></code></pre></li><li> Daily Revenue - $DailyRevenue$ . The feature is calculated as a percentage of $Close$ values between present and previous days [1]<br />$DailyRevenue = \frac{( Close[k] - Close[k-1] )}{Close[k-1]} \cdot 100$ <pre class="prettyprint"><code>input$DailyRevenue <- 0<br />input$DailyRevenue[1] <- 0<br />for (k in (2:(length(input$Close)))) {<br /> input$DailyRevenue[k] <- (input$Close[k]-input$Close[k-1])*100/(input$Close[k-1])<br />}<br /></code></pre></li><li> Censors: <br />In this case I consider two series of censored data corresponding to the increasing and decreasing values of $DailyRevenue$. The increasing or decreasing event is detected by checking whether the Daily Revenue is larger or smaller than a given threshold value. The threshold value could be used as a parameter in our model. Therefore, the value of the $threshold$ could be different from $0$ ($0$ is here a good initial choice). The censoring of data used in the model is following: <ol><li>censors specific for increasing daily revenue: $censorUp$: if the daily revenue is higher than $threshold$: $censorUp = 0$ (censored point of time). In case when the daily revenue being smaller or equal to $threshold$: $censorUp = 1$ . <pre class="prettyprint"><code>Threshold <- 0<br />input$censorUp <- 0<br />input[input$DailyRevenue <= Threshold,12] <- 1<br /></code></pre></li><li>censors specific for decreasing daily revenue: $censorDown$. In this case the events are opposite to the $censorUp$ feature. The daily revenue is smaller or equal to $threshold$: $censorDown = 1$ . the daily revenue is larger than $threshold$: $censorDown = 0$ . <pre class="prettyprint"><code>input$censorDown <- 0<br />input[input$DailyRevenue > Threshold,11] <- 1<br /></code></pre></li></ol></li><li> Time to events: are measured as a time distance between last local extremum of the $DailyRevenue$ and an event defined by censoring series (censored or NOT censored). <ol><li> $TimeToEventUp$: <br />it is a time measured from a last local minimum of the $DailyRevenue$ to the $censorUp = 1$ events or the time distance between the last local maximum of the $DailyRevenue$ to the $censorUp = 0$. <pre class="prettyprint"><code>locmylastmin <- 1<br />locmylastmax <- 1<br /><br />for (k in (2:(dim(input)[1]))) {<br /> tmp <- input$DailyRevenue[1:k]<br /> if (input$censorUp[k] == 0) {<br /> # find all local minima:<br /> locmymin <- which(diff(sign(diff(tmp)))==+2)+1<br /> if (length(locmymin) == 0) {locmymin <- which.min(tmp)}<br /> locmylastmin <- locmymin[length(locmymin)]<br /> dateMin <- input[locmylastmin,1]<br /> input$TimeToEventUp[k] <- as.integer(as.Date(input[k,1])-<br /> as.Date(dateMin))<br /> }<br /> if (input$censorUp[k] == 1) {<br /> # find all local maxima:<br /> locmymax <- which(diff(sign(diff(tmp)))==-2)+1<br /> if (length(locmymax)==0) {locmymax <- which.max(tmp)}<br /> locmylastmax <- locmymax[length(locmymax)]<br /> dateMax <- input[locmylastmax,1]<br /> input$TimeToEventUp[k] <- as.integer(as.Date(input[k,1])-<br /> as.Date(dateMax))<br /> }<br />}<br /></code></pre> </li><li>$TimeToEventDown$: <br />is calculated in an opposite way to the feature $TimeToEventUp$. Details of determination of the $TimeToEventDown$ feature is shown on Fig. 1 . <pre class="prettyprint"><code>locmylastmin <- 1<br />locmylastmax <- 1<br /><br />for (k in (2:(dim(input)[1]))) {<br /> tmp <- input$DailyRevenue[1:k]<br /> if (input$censorDown[k] == 1) {<br /> # find all local minima:<br /> locmymin <- which(diff(sign(diff(tmp)))==+2)+1<br /> if (length(locmymin) == 0) {locmymin <- which.min(tmp)}<br /> locmylastmin <- locmymin[length(locmymin)]<br /> dateMin <- input[locmylastmin,1]<br /> input$TimeToEventDown[k] <- as.integer(as.Date(input[k,1])-<br /> as.Date(dateMin))<br /> }<br /> if (input$censorDown[k] == 0) {<br /> # find all local maxima:<br /> locmymax <- which(diff(sign(diff(tmp)))==-2)+1<br /> if (length(locmymax)==0) {locmymax <- which.max(tmp)}<br /> locmylastmax <- locmymax[length(locmymax)]<br /> dateMax <- input[locmylastmax,1]<br /> input$TimeToEventDown[k] <- as.integer(as.Date(input[k,1])-<br /> as.Date(dateMax))<br /> }<br />}<br /></code></pre> <!-- <a href="https://4.bp.blogspot.com/-Tr0lgdGbFbU/V2qD2oMLVPI/AAAAAAAAAEo/ndRf3GwlrgMFJEGblOAl1fDZan2KDcsIQCKgB/s1600/censoring.bmp" imageanchor="1" ><img border="0" src="https://4.bp.blogspot.com/-Tr0lgdGbFbU/V2qD2oMLVPI/AAAAAAAAAEo/ndRf3GwlrgMFJEGblOAl1fDZan2KDcsIQCKgB/s1600/censoring.bmp" /></a><b>Fig. 1</b>--> <a href="https://4.bp.blogspot.com/-Tr0lgdGbFbU/V2qD2oMLVPI/AAAAAAAAAEo/ndRf3GwlrgMFJEGblOAl1fDZan2KDcsIQCKgB/s1600/censoring.bmp" imageanchor="1" ><img border="0" src="https://4.bp.blogspot.com/-Tr0lgdGbFbU/V2qD2oMLVPI/AAAAAAAAAEo/ndRf3GwlrgMFJEGblOAl1fDZan2KDcsIQCKgB/s640/censoring.bmp" /></a>Definition of the variable $TimeToEventDown$ demonstrated on a part of the $DailyRevenue$ time series. It is a sequence of time distances $T_{Down}^{censored}$ and $T_{Down}^{event}$, where the time $T_{Down}^{censored}$ is a time measured from a last local maximum of the $DailyRevenue$ to the $censorDown = 0$ and $T_{Down}^{event}$ - is the time distance between the last local $DailyRevenue$ minimum to the $censorDown = 1$. <br /> </li></ol></li></ol><br />In the next step I build the signal creator. <br />The basic part is realized in the standard way of calculating of the survival probabilities corresponding to the both series $censorUp$ and $censorDown$. The prediction is calculated by the function survfit without newdata object. In such a case the predicted survival probabilities are calculated on a base of mean values of all covariates included in the formula used for creation of the Cox hazards regression model fit. In our case I use all available covariates in implemented formula, except the $Volume$ feature which is not already a solid number. <pre class="prettyprint"><code>formula = Surv(TimeToEventDown, censorDown) ~ <br /> High + Low + Close + corp + EMAV + DailyRevenue + OpenInt<br /></code></pre> The code of the function $SurvivalProb$: <pre class="prettyprint"><code>SurvivalProb <- function(myinput,What="Down") { <br /> train <- myinput<br /> if (What == "Down") {<br /> coxphCorp <- coxph(Surv(TimeToEventDown, censorDown) ~ <br /> High + Low + Close + corp + EMAV + DailyRevenue + OpenInt, <br /> data=train, method="breslow")<br /> }<br /> if (What == "Up") {<br /> coxphCorp <- coxph(Surv(TimeToEventUp, censorUp) ~ <br /> High + Low + Close + corp + EMAV + DailyRevenue + OpenInt, <br /> data=train, method="breslow")<br /> }<br /> mysurffit<-survfit(coxphCorp, se.fit = F, conf.int = F)<br /> <br /> tmp<-summary(mysurffit)<br /> myprob <- tmp$surv[1]<br /> <br /> myprob<br />}<br /></code></pre> The function predicting the signal sell/buy ($SignalPredictor$) calculates it as a ratio between probabilities calculated for the next days related to the increased and decreased daily revenue accordingly. The ratio is defined as: $ratio = \frac{Survival-Probability-that-daily-revenue-will-be-higher-next-day}{Survival-Probability-that-daily-revenue-will-be-smaller-next-day} - \left(1+\epsilon\right)$ where $Survival-Probability-that-daily-revenue-will-be-higher-next-day$ (denoted as $probUp$ in the code) and $Survival-Probability-that-daily-revenue-will-be-smaller-next-day$ ($probDown$ in the code) are calculated by the function $SurvivalProb$. The constant $1+\epsilon$ corresponds to the $ratioValue$ inside the code. <br />The code of the function $SignalPredictor$ : <pre class="prettyprint"><code>SignalPredictor <- function(train,ratioValue) { <br /><br /> # Survival-Probability-that-daily-revenue-will-be-smaller-next-day <br /> ProbDown <- SurvivalProb(train,"Down") <br /> <br /> # Survival-Probability-that-daily-revenue-will-be-higher-next-day<br /> ProbUp <- SurvivalProb(train,"Up") <br /> <br /> # signal: + <- buy; - <- sell<br /> signal <- ((ProbUp/ProbDown)-ratioValue)<br /> signal <br />}<br /></code></pre> As a practical test how well the model creates buy-sell signals I run the signal predictor in a loop over available dates in the set of historical data of Brent Oil Future. In the code below, the $Dist$ variable denotes the size of the training sample. For a given row $k$ the model use $Dist$ rows in the data as a train sample and makes a prediction for the day: $k + Dist + 1$ ($SignalPredictor$). In the next iteration the model predicts signal for the next day $k + Dist + 2$, using data of the previous day $k + Dist + 1$ as a part of the train sample. <br /> <pre class="prettyprint"><code># daily step:<br />Dist <- 50 <br />ratioValue <- 1.02<br />Bias <- 0 <br />startInd <- Dist<br />results <- NULL <br />results$Signal <- 0<br /><br />for (k in seq((startInd+Bias+1),length(input[,1]),by=1)) {<br /> print(as.Date(input[k,1]))<br /> train <- input[(k-Dist):k,]<br /> train <- Optimize(train,ratioValue)<br /><br /> ratio <- SignalPredictor(train,ratioValue) <br /> results$Signal <- c(results$Signal,ratio)<br />}<br /></code></pre> Inside the loop I use another function $Optimize$. The $Optimize$ function takes the train sample and selects its last row as test data. In the next steps the function selects such a size of the train sample that properly predicts the sign of the $DailyRevenue$ feature from the test sample (e.g. the signal sell/buy corresponds to the sign of the $DailyRevenue$ variable). The resulting size of the train sample can be smaller or equal to the initial train size. The $Optimize$ function:<br /><pre class="prettyprint"><code>Optimize <- function(inputData,ratioValue) {<br /> L <- dim(inputData)[1]<br /> mydist <- 1<br /> mycheck <- -1<br /> <br /> repeat {<br /> mytest <- inputData[L,]<br /> mytrain <- inputData[mydist:(L-1),]<br /> <br /> probDown <- SurvivalProb(mytrain,"Down")<br /> probUp <- SurvivalProb(mytrain,"Up")<br /> <br /> ratio <- (probUp/probDown)-ratioValue<br /><br /> if ( (sign(ratio)*mytest$DailyRevenue >= 0) ) {mycheck <- 1} <br /> if (mycheck == 1) {break} <br /> if (mydist >= (L-10)) {<br /> mycheck <- 1;mydist <- 2;break<br /> }<br /> mydist <- mydist + 1<br /> }<br /> mydist <- mydist - 1 <br /> inputData[mydist:L,]<br />}<br /></code></pre> The results (sell=buy signals) are shown on the next plot (Fig.2) for an initial values of parameters: <pre class="prettyprint"><code>Dist <- 50 <br />ratioValue <- 1.02<br />Threshold <- 0<br /></code></pre>and for the date period: 2015-03-13 - 2016-06-16 <div class="separator" style="clear: both; text-align: center;"><a href="https://3.bp.blogspot.com/-tT0TTn3zr2M/V2hOuqOp4II/AAAAAAAAAEQ/uyUGSti59NAGhrSgVvhU9gqbW975-7MbQCLcB/s1600/Predictions.jpeg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://3.bp.blogspot.com/-tT0TTn3zr2M/V2hOuqOp4II/AAAAAAAAAEQ/uyUGSti59NAGhrSgVvhU9gqbW975-7MbQCLcB/s1600/Predictions.jpeg" /></a></div><b>Fig. 2</b><br /><!-- <div class="separator" style="clear: both; text-align: center;"><a href="https://1.bp.blogspot.com/-bryFUrzk-JU/V2hLgJTU_7I/AAAAAAAAAEE/ps73BzSLILI7Ep0UonzlJ4l_yg9GJQpqQCLcB/s1600/Predictions.jpeg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://1.bp.blogspot.com/-bryFUrzk-JU/V2hLgJTU_7I/AAAAAAAAAEE/ps73BzSLILI7Ep0UonzlJ4l_yg9GJQpqQCLcB/s400/Predictions.jpeg" /></a></div>--> In the Fig. 2 the green parts correspond to the positive values of the ratio where the calculated probability for increasing $Close$ price is larger than for decreasing one. The red part shows the opposite behaviour. <br />The best signal buy/sell is generated when the ratio changes the sign:<br /> <b>from red to green : buy, from green to red: sell</b> .<br />The black curve presents the $Close$ values, the blue line represents the values of $EMAV$. <br />By manipulating with the above parameters ($Dist$,$ratioValue$, $Threshold$ and $EMAV$) one can create different strategies. Using an initial capital equal to the $Close$ value at the initial date of the game, the total income generated by buy and sell signals for the above period and parameters is $16.47$ USD what corresponds to the $41.1$ % of profit from the considered period of time (2013-03-13 - 2016-06-17) .<br /><br /><h4>Conclusions:</h4><br />If you place capital into financial market it is always better to use several independent models for prediction of behaviour of financial instruments. If most of the methods are coming to the same conclusions, one can decide to take action: to sell or to buy the instrument(s). <br /> The presented model could be treated as an additional source of such a knowledge. From technical point of view the script is easy to adopt to any financial data and has a lot of room for improvement. The most important part of the algorithm is the definition of censors ($censorUp$,$censorDown$) and "time to event" ($TimeToEventUp$,$TimeToEventDown$). I would appreciate any hints concerning improvement of the algorithm. <br /><br /> Hope, the note could be used as an introduction for survival analysis in a financial market. Comments (and links) are very welcome. <br /><br /><br /> Thanks for reading ! <br />Bogdan Lobodzinski<br /><a href="http://dataanalytics4all.site/">Data Analytics For All Consulting Service</a><br /> <br />[1] Guangliang Gao, Zhan Bu, Lingbo Liu, Jie Cao, Zhiang Wu: A survival analysis method for stock market prediction. BESC 2015: 116-122<br /><br />Code for generation Fig. 2:<br /><pre class="prettyprint"><code>shift <- 47<br />factorSig <- 21<br />Sig <- sign(results$Signal)<br />L<-length(Sig)<br />Sigdf <- data.frame(x=input[(startInd+Bias):length(input[,1]),1],Sig=Sig*factorSig) <br />JustLine <- data.frame(xTime=input[(startInd+Bias):length(input[,1]),1],Line=0*c(1:L)+shift) <br />titleStr <- paste("Brent Oil Future: period from ",as.Date(input[(startInd+Bias+1),1]),<br /> " to", as.Date(input[(length(input[,1])),1]))<br /><br />ggplot(Sigdf, aes(x=as.Date(x), y=Sig+shift)) +<br /> geom_line() + <br /> geom_ribbon(aes(ymin=shift, ymax=ifelse(Sig+shift>shift,Sig+shift,shift)),<br /> fill = "green", alpha = 0.5,colour = "green") +<br /> geom_ribbon(aes(ymin=ifelse(Sig+shift < shift,Sig+shift,shift),ymax=shift),<br /> fill = "red", alpha = 0.5,colour="red") + <br /> geom_line(data = JustLine, aes(x=as.Date(xTime), y=Line)) + <br /> geom_line(data = input[(startInd+Bias+1):length(input[,1]),], <br /> aes(x=as.Date(input[(startInd+Bias+1):length(input[,1]),1]), y=Close)) +<br /> geom_line(data = input[(startInd+Bias+1):length(input[,1]),], <br /> aes(x=as.Date(input[(startInd+Bias+1):length(input[,1]),1]), y=EMAV, colour=4)) + <br /> ggtitle(titleStr) +<br /> labs(x="Date", y="Price in USD") +guides(colour=FALSE)<br /></code></pre>Bogdan Lobodzinskihttp://www.blogger.com/profile/09289422592105592639noreply@blogger.com0tag:blogger.com,1999:blog-4412689276279452501.post-91842621551610703362016-05-06T15:33:00.002+02:002021-05-14T21:51:20.981+02:00Mainstream media and shaping social opinions<!-- MathJax usage example --><script type="text/x-mathjax-config">MathJax.Hub.Config({tex2jax: {inlineMath: [['$','$'], ['\\(','\\)']]}}); </script> <script src="https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML" type="text/javascript"> </script> Inspired by a question <b>"What can we learn about social behaviour from recommender database ?"</b> which arises from my previous note <a href="http://dataanalyticsforall.blogspot.de/2016/03/recommender-systems-and-q-value-potts.html">Recommender Systems and q-value Potts model</a>I spent some time considering a following question: <br /><b>The question:</b><br />how to control opinions in a social group by creation of an environment with whom the group can interact ?<br /><br /> Let us start to define the toy model. <br />In a given social group we have a set of opinions $K$ distributed among all group members. The group collaborates with external world through an interaction with some set of opinions stated in an external environment. We assume that the environment is too big to be manipulated by the social group, but the environment can modify somehow the distribution of opinions inside the group.<br />For a better transparency we consider 2 different opinions described as $A$ and $B$. Opinions $A$ and $B$ are defined as states <b>"+1"</b> and <b>"-1"</b> correspondingly. Members are distributed among two subgroups according to a shared opinion and interact with the same environment but with different strength: $\gamma_{A}$ and $\gamma_{B}$ respectively. The $\gamma_{A|B}$ coefficients correspond to the level of group members acceptance of noise created by the environment. Or, in other words, the coupling constants $\gamma_{A|B}$ are weights which characterize how much a given group relies on opinions supported by the environment. The level of believe in a group is proportional to the value of $\gamma_{i}$ couplings. The scheme is depicted in the picture 1.<br /><br /> <div class="separator" style="clear: both; text-align: center;"><a href="https://3.bp.blogspot.com/-hQj_cLqqqCU/VyxdHupnLmI/AAAAAAAAADQ/9v6fYv3HrJw_YFwfjkJ8uBsnU-Cn9NiiwCLcB/s1600/fig1.bmp" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://3.bp.blogspot.com/-hQj_cLqqqCU/VyxdHupnLmI/AAAAAAAAADQ/9v6fYv3HrJw_YFwfjkJ8uBsnU-Cn9NiiwCLcB/s320/fig1.bmp" /></a></div><br />fig. 1. The environmental $M$ levels are coupled to 2 separate systems $A$ and $B$ with a given coupling constants $\gamma_{A}$ and $\gamma_{B}$. For simplicity each group $A$ and $B$ has the same number of levels $N$. <br /><br /><br /><br /><br /><br /><br /><br />We assume that the social model will fulfill the principle of least action so the entire set will tend to minimize the total energy. Therefore the Hamiltonian approach should make a frame for our analysis. The model can be described by the following Hamiltonian: \begin{equation} \label{Hamiltonian0} H = H_{A} + H_{B} + H_{E} + H_{Int} \end{equation} where <br /> \begin{equation} \label{Hamiltonian1} H_{A|B} = \sum_{k_{A|B} = 1}^{N_{A|B}} E_{A|B} \left| A|B_{k_{A|B}} \right> \left< A|B_{k_{A|B}} \right| \end{equation} describes the state of subgroups $A$ and $B$ with energies $E_{A}$ ($E_{A}$) and $N_{A}$ ($N_{A}$) discrete states $\left| A_{k_{A}} \right>$ ($\left| B_{k_{B}} \right>$). \begin{equation} \label{Hamiltonian2} H_{E} = \sum_{n = 1}^{M} E_{n} \left| E_{n} \right> \left< E_{n} \right| \end{equation} is the basic energy of the environment with $M$ discrete states $\left| E_{n} \right>$ labeled by index n. The interaction between the groups and the environment has a form: \begin{equation} \label{Hamiltonian3} H_{Int} = \sum_{n=1}^{M} \left[ \left( \sqrt{ \gamma_{A} } \sum_{ k_{A} = 1}^{ N_{A} } VA_{k_{A}}^{n} \left| A_{k_{A}} \right> \left< E_{n} \right| + h.c. \right) + \left( \sqrt{ \gamma_{B} } \sum_{ k_{B} = 1}^{ N_{B} } VB_{k_{B}}^{n} \left| B_{k_{B}} \right> \left< E_{n} \right| + h.c. \right) \right ] \end{equation} where $VA$ and $VB$ are matrix elements describing couplings between group states $\left| A \right>$, $\left| B \right>$ and environmental levels $\left< E_{n} \right|$. <br />Because the environment cannot be modified by any group we can use the Markovian approximation and eliminate the environment states from the Hamiltonian above. The result of operation can be written in the following form: \begin{equation} \label{Hamiltonian4} H_{eff} = H_{A} + H_{B} - i V \cdot V^{+} \end{equation} where \begin{equation} \label{Hamiltonian5} V = \left( \begin{array}{} \sqrt{ \gamma_{A} } \cdot VA \\ \sqrt{ \gamma_{B} } \cdot VB \end{array} \right) \end{equation} creates a dissipative part of the effective Hamiltonian $H_{eff}$ which is an $N \times N$ dimensional matrix and matrix $V$ has a dimension $N \times M$ . Our analysis of the dynamics of the system can be reduced to the determination of the eigenvalues of the effective Hamiltonian $H_{eff}$: $\Lambda = x - iy$ which are complex. An imaginary part describes how fast (time $\tau$) a given eigenvalue dissipates in the system: $ \tau \approx \frac{1}{y}$. <br />In other words, the $\tau$ describes the lifetime of a given opinion values by the real value of the eigenvalue $x$ . Let us stress that we allow to create a continuous number of opinions, not only those which are defined in the assumptions of the issue: $E_{A|B}$ . Why can the eigenvalues of the Hamiltonian be used as a determinant of the social opinion distribution ?<br />A standard model of opinion evolution is modeled using (in a simplest case) a set of linear equations: \begin{equation} \label{Hamiltonian6} \vec{x} \left( t + 1 \right) = W \vec{x} \left( t \right) \end{equation} where $W$ is some $N\times N$ matrix describing an information exchange with weights between participants of the social network and the vector $\vec{x}$ is an opinion profile in the network calculated for the time $t$. Thus, the correspondence between the opinion profile $\vec{x}\left( t \right)$ and our approach can be done by calculation of a power spectrum of the $\vec{x}\left( t \right)$. Positions of maximums in the power spectrum can be understood as equivalent to the real values of eigenvalues of the Hamiltonian $H_{eff}$ while the time scale of change of the profile $\vec{x}\left( t \right)$ corresponds to the imaginary part of the eigenvalues (to be more specific to the inverse of the imaginary part).<br /> For any numerical calculations we have to define values $M$, $N$, $E_{A}$, $E_{B}$, $N_{A}$, $N_{B}$, $\gamma_{A}$, $\gamma_{B}$. The matrices $VA$ and $VB$ are calculated as Gaussian unitary ensembles (GUE random matrices). <br /> Below we present a variety of plots of numerically determined eigenvalues of the Hamiltonian. <br />On all plots the dots are a result of numerical calculations of the Hamiltonian $H_{eff}$. Numerical simulations have been done for 30 GUE matrices $V$ with $N = 100$ and $M = 60$. Remaining values of parameters used for simulations: <br /> <ol><li> energies: $E_{A} = -1/2$, $E_{B} = 1/2$, <li> number of states: for state $A$: $N_{A} = 50$, for state $B$: $N_{B}=50$, <li> interaction couplings are described for each plot separately. </ol><br /> At the beginning, for a comparison with existing models we shows on Fig. 2,3 and 4 a situation where $\gamma_{A} = \gamma_{B}$ and different values of $\gamma_{B}$. A similar plots one can find in the work [1]. <br />For a better visibility we used for scale $y$ logarithmic scale. In our case $y \leftarrow -log( \left| y \right| )$, so the value $y=-3$ corresponds to $y = 10^{-3}$. <br /> <br /><div class="separator" style="clear: both; text-align: center;"><a href="https://1.bp.blogspot.com/-tg_l9_FwHM0/VyukeyJgfJI/AAAAAAAAACg/QAri6I5_kkIf_eL2t-esniyMn2Gw5XwdQCLcB/s1600/fig_Re8_Im8.jpeg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://1.bp.blogspot.com/-tg_l9_FwHM0/VyukeyJgfJI/AAAAAAAAACg/QAri6I5_kkIf_eL2t-esniyMn2Gw5XwdQCLcB/s320/fig_Re8_Im8.jpeg" /></a></div><br />Fig. 2. Simulation for $\gamma_{A} = \gamma_{B} = 0.0025$ in energy units. The left vertical plot shows the integrated density profile of the width of calculated eigenvalues. The upper picture presents the integrated spectral density showing the width of energy states. <br /> <br /><div class="separator" style="clear: both; text-align: center;"><a href="https://4.bp.blogspot.com/-P1FAWw4Gzb4/VyukrhqM00I/AAAAAAAAACk/lfcZYq_a_5MimHNsqgyG1AfRZg58gndLQCLcB/s1600/fig_Re7_Im7.jpeg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://4.bp.blogspot.com/-P1FAWw4Gzb4/VyukrhqM00I/AAAAAAAAACk/lfcZYq_a_5MimHNsqgyG1AfRZg58gndLQCLcB/s320/fig_Re7_Im7.jpeg" /></a></div><br />Fig. 3. Simulation for $\gamma_{A} = \gamma_{B} = 0.01$. An creation of two timescales of the eigenvectors is visible.<br /><br /> <div class="separator" style="clear: both; text-align: center;"><a href="https://4.bp.blogspot.com/-uA4CIw8QCIg/VyukymQm12I/AAAAAAAAACo/Zc0lU9C1KYAmjenX2bIgT58hQmrJT_ujACLcB/s1600/fig_Re6_Im6.jpeg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://4.bp.blogspot.com/-uA4CIw8QCIg/VyukymQm12I/AAAAAAAAACo/Zc0lU9C1KYAmjenX2bIgT58hQmrJT_ujACLcB/s320/fig_Re6_Im6.jpeg" /></a></div><br />Fig. 4. Simulation for $\gamma_{A} = \gamma_{B} = 0.5$. <br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br />The next Figs (5,6,7 and 8) shows asymmetric situations where $\gamma_{A} = \gamma_{B}/10$ and different values of $\gamma_{B}$. Detailed values of other parameters are noted in the figure description. <br /><br /> <div class="separator" style="clear: both; text-align: center;"><a href="https://3.bp.blogspot.com/-uT4cBiBqMOE/VyulQfCVpoI/AAAAAAAAACs/cgRY16O6axofob1aUQOkwrkmtJ3mx25wACLcB/s1600/fig_Re2_Im2.jpeg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://3.bp.blogspot.com/-uT4cBiBqMOE/VyulQfCVpoI/AAAAAAAAACs/cgRY16O6axofob1aUQOkwrkmtJ3mx25wACLcB/s320/fig_Re2_Im2.jpeg" /></a></div><br />Fig. 5. The situation with $\gamma_{B} = 0.01$ and $\gamma_{A} = \gamma_{B}/10$. <br /><br /> <div class="separator" style="clear: both; text-align: center;"><a href="https://3.bp.blogspot.com/-4XNspCZg2gM/VyulVW4YuyI/AAAAAAAAACw/xWYOISOVHekS4N2ZYRncu0o_1JsXozJCQCLcB/s1600/fig_Re3_Im3.jpeg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://3.bp.blogspot.com/-4XNspCZg2gM/VyulVW4YuyI/AAAAAAAAACw/xWYOISOVHekS4N2ZYRncu0o_1JsXozJCQCLcB/s320/fig_Re3_Im3.jpeg" /></a></div><br />Fig. 6. The eigenvalue spectrum calculated for $\gamma_{B} = 0.05$ and $\gamma_{A} = \gamma_{B}/10$. <br /><br /> <div class="separator" style="clear: both; text-align: center;"><a href="https://2.bp.blogspot.com/-Pp8lOfK5IdQ/VyxhKQ4xiEI/AAAAAAAAADc/gnmnpajJxFINtErqVhk6nqSag_FH7Zw1gCLcB/s1600/fig_Re_Im_gamma_0.1.jpeg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://2.bp.blogspot.com/-Pp8lOfK5IdQ/VyxhKQ4xiEI/AAAAAAAAADc/gnmnpajJxFINtErqVhk6nqSag_FH7Zw1gCLcB/s320/fig_Re_Im_gamma_0.1.jpeg" /></a></div><br />Fig. 7. The spectrum calculated for $\gamma_{B} = 0.1$ and $\gamma_{A} = \gamma_{B}/10$. <br /> <br /> <div class="separator" style="clear: both; text-align: center;"><a href="https://2.bp.blogspot.com/-ILeoofh0mPE/Vyulac7YduI/AAAAAAAAAC4/kU5574t4I6c-WkTevCrAW_xvpUOTAnNZwCLcB/s1600/fig_Re4_Im4.jpeg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://2.bp.blogspot.com/-ILeoofh0mPE/Vyulac7YduI/AAAAAAAAAC4/kU5574t4I6c-WkTevCrAW_xvpUOTAnNZwCLcB/s320/fig_Re4_Im4.jpeg" /></a></div><br />Fig. 8. The spectrum calculated for $\gamma_{B} = 0.5$ and $\gamma_{A} = \gamma_{B}/10$. <br /><br /> <br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><h4>Conclusions </h4><br />The landscape presented on all plots of eigenvalues of the Hamiltonian $H_{eff}$ is quite straightforward for those who are familiar with atomic physics, especially interactions of multi-level atomic transitions with resonant light. We see clear existence of so called coupled and uncoupled level (states) combinations . The increase of the coupling constant $\gamma_{A|B}$ leads to a creation of grouping of eigenvalues. <br />The eigenfunctions in the Hamiltonian can be formed in such a way that some combinations of levels cancel the interaction part with the environment - they are called uncoupled (or trapped) states. The number of such states is $N-M$. <br />Other level eigenfunctions are coupled with the environment's states - such an eigenfunction we call coupled (or un-trapped) states ($M$ decaying states). Populations of trapped states can survive longer time (smaller values of y) in comparison to the un-trapped states, where the populations is exchanged between coupled states by the interaction term proportional to $\sqrt{\gamma_{A|B}}$. <br /> Let us try to translate this physical picture into a social language. <br /><ol><li> The coupled (un-trapped) states: configurations of members (eigenfunction) which change a common opinion (eigenvalue) faster due to the interaction with a noisy environment represented by a different set of environmental opinions. Such an exchange of opinion is proportional to the interaction strength $\gamma_{i}$ ($i=A|B$). <li> The uncoupled (trapped) states: ideally, such configurations of members (eigenfunction) which create a stable combinations of a group members. They do not interact with the environment. </ol> If we define an opinion power as a parameter proportional to the number of eigenfunctions which share the same range of opinions we see that in steady-state conditions the opinion created by the trapped states (i.e. weakly coupled with the environment) has a greater power of persuasion than an opposite social group characterized by the un-trapped member's configurations (i.e. strongly coupled to the environment). <br />A higher level of noise (larger value of $\gamma_{A|B}$ and different values of couplings $\gamma_{A} < \gamma_{B}$) doesn't lead to reduction of a significance of unwanted opinions but creates just the opposite action: <br />it sharpens the polarization of existing opinions and increases the importance of resistance against the environment in a society. Such a situation can be well identified nowadays. The noisy environment is created by mainstream media. What one can find in such an environment: an increasing number of different subjects, news focused on accidents, preferred shorter forms and propagation of a number of opposite opinions and many other similar, as well as different ways of distraction of reader's attention.<br /> Groups of people strongly coupled to such a media stream are not able to define a private opinion and they are easy to manipulate. It also means that the number of people in such a chaotic environment will migrate rather to more stable social groups (trapped states), not so strongly dominated by the mainstream news. <br /> The creation of people without a strong, private opinions is a goal of the present liberal governments. But, as it is presented in this note the chosen way of social control leads just to opposite behaviour. You can see it around yourself, don't you ? <br /> In the model, we used the condition where the number of intermediate states in the environment $M$ is smaller that the number of states in considered social groups $N$: $M < N$. <br />The opposite case leads to a bit different picture than described in this note, but it is a subject for an another post.<br /><br /><br />Bogdan Lobodzinski<br /><a href="http://dataanalytics4all.site">Data Analytics For All Consulting Service</a><br /><br /> <h4>References: </h4><ol><li> E.Gudowska-Nowak, G. Papp and J. Brickmann, Two-Level System with Noise: Blue's Function Approach, Chem. Phys., 220 120-135 (1997) </ol>Bogdan Lobodzinskihttp://www.blogger.com/profile/09289422592105592639noreply@blogger.com0tag:blogger.com,1999:blog-4412689276279452501.post-82908904585894345182016-04-10T22:09:00.001+02:002020-01-21T21:04:49.791+01:00Small and medium-size companies: any chance to grow in the Big Data dominated environment ?Today I watched a video presenting European Truck Platooning Challenge 2016.<br />For those who are not familiar with the subject, it is about a test of self-driving trucks across Europe. The test was organized by the Dutch government. Main truck companies from Europe participated in running the event. You can watch the video here <a href="http://www.engadget.com/2016/04/07/european-truck-platooning-challenge-video/">here</a>and <a href="https://www.eutruckplatooning.com/default.aspx">here</a>. <br /> It is a really great proof-of-concept project driven by the Big Data technologies. <br /><br />However, in this note I don't like to write about details of the project. Instead, I would like to develop wider my first reflections after watching the video. I think everyone's conclusion will be that with this event all smaller transportation enterprises have got a Big problem. The problem can be verbalize by a question:<br /><i>how to survive on the market dominated by big transportation players and their self-driving trucks across Europe ?</i><br />In the big transport companies the drivers will be replaced by the lawyers, but what about smaller transport businesses ? <br /><br />Of course the problem is not only related to the transport industry. Similar situation appears in each branch of commerce. Therefore, the more general question, is:<br /><b><i>how smaller enterprises can find themselves in the business environment dominated by the Big Data technologies governed by big parties ?</i></b><br />It is a bit similar to the competition between members inside a social group:<br /><i>how to survive in a group dominated by set of rules profitable mainly for those who created those regulations</i>. <br />Each of us can find clear example of such an environment from his own experience. <br /><br />In my opinion, a possible solution of the problem can be found in a grouping of small companies into a fair-shared societies glued by common goals and business activity. Such a group has a bigger chance of survival than a single member, especially if all members can coordinate all individual actions, in such a way that only these processes which are profitable for the group and for the participant should be realized. It may sound like a socialism utopia - so it may mean - forget it, not possible for realization. <br /><br />However, I am more and more convinced that such a procedure of business activity is possible if all human emotional behavior can be removed from a decision making processes. Remember, we are talking about methods to lead business in a most effective way. Such a decision creator can be realized by a Big Data driven decision making system using machine learning algorithms . If we have a group of a few enterprises and each company makes available his business data (like details of contacts, details of realized tasks and preferences, etc. ) for the decision-making system, a proper Big Data framework can create suggestions how to move forward using well established probabilities.<br />A client can look for a doer by communications with a group accessing the representative portal providing specification of task(s), or asking directly a chosen company.<br />In opposite, each group member can act fully autonomously, looking for customers individually or can use a group representative hints created by the decision-making system. In both cases the group representative framework acts as a Data driven decision creator: <br /><ol><li> for customer: suggesting proper companies from the group <li> for companies in the group: informing chosen entities about requested tasks. </ol> The structure of the group reminds a bit the franchise business model. In contrary to a franchiser a group member don't have to follow any business concept and there is no need for any kind of standardizations in terms of provided services. The only payment which have to be provided by the group participants is a cost of the service and the development of a proper "Big Data"/Machine Learning infrastructure. <br /><br />Summarizing this short note, the goal of described above business association is creation and support of strategies for sustainable growth of small sized enterprises in a Big Data dominated environment. The common features among all participating parties in the group should be community of the type of business activity and goals. <br /><br />Unfortunately, details are usually much mode complicated, but my intention was to sketch a general picture of a structure with (in my opinion) a highest chance to become profitable in the Big Data business era. <br /><br /> I will appreciate any comment and opinion about the idea sketched above. <br /><br /><br />Bogdan Lobodzinski <br /><a href="http://dataanalytics4all.site/">Data Analytics For All Consulting Service</a>Bogdan Lobodzinskihttp://www.blogger.com/profile/09289422592105592639noreply@blogger.com0tag:blogger.com,1999:blog-4412689276279452501.post-34288504385618041952016-03-13T19:46:00.005+01:002021-05-14T21:51:35.498+02:00Recommender Systems and q-value Potts model<!-- MathJax usage example --><script type="text/x-mathjax-config"> MathJax.Hub.Config({tex2jax: {inlineMath: [['$','$'], ['\\(','\\)']]}}); </script> <script src="https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML" type="text/javascript"> </script> <br /><h4>Introduction</h4><br /><br />Recommendation system (RS) can be described in a general way as a class of applications used to predict a set of items with highest probability of acceptance by a given user and is based on user's responses. The RS connects users with items and it is usually described from the point of view of the performance of algorithms used in the system. <br />In this note I would like to raise the following question: <b>what can we learn by applying a q-valued Potts model to datasets created by recommender system ?</b>The Potts model describes interaction of a set of spins distributed on a lattice. In contrary to Ising model, spins in the $q$-valued Potts formulation can take $q$ possible states (values). <br /><br /><h4>Analysis</h4><br />Let us consider a database created by a given RS where each item is characterized by a set $\{rating,tag\}$. Both, the $rating$ and $tag$ values are determined by independent users. From the $tag$ value one can extract a set of users who tagged the item. Those users make an $y$ coordinate. The $x$ coordinate is created by the users who made $rating$ instances. Both coordinates can be used for creation of $x-y$ lattice with $z$ values corresponding to the $rating$ variable. <br />It is obvious that the available items and users evolve with time in some way. Therefore it is not possible to determine close neighbours of a given spin placed in a lattice point $\{x,y\}$. In order to avoid this problem I assume that all spins on the lattice can interact with each other with the same coupling constant equal 1. After such assumptions the data can be described as the long-ranged $q$-value Potts model with parameter $q$ corresponding to the number of voting options. Using mathematical notations, for a given time $t$ we have $x-y$ lattice occupied by spins $\sigma_{i} = 1,..,q$ . The lattice (graph) state is described by the energy $E$ due to the interaction between spins $\sigma_{i}$: \[ E = - \sum_{i,j} \delta_{\sigma_{i},\sigma_{j}} \] and by the order parameter (also known as a magnetisation) $M$ defined as \[ M = \frac{\left( q \max\{n_{i}\} - N \right)}{\left(q-1\right)} . \] In the formulas above: $\delta$ is the Kronecker symbol, $N$ is the total number of spins in the lattice, $n_{i} <= N$ denotes the number of of spins with orientations $\sigma_{i}$. <br />Each graph is described by the per-graph quantities: $e = E/N$ and $m = M/N$ . The maximum order in a graph corresponds to $m = 1$ and is equivalent to all spins with the same orientation. The perfect disorder is specific for a case when all orientations are equally numerous: $\max\{n_{i}\} = N/q$, this state corresponds to $m = 0$. As a data for the model I used the movie dataset [1]. The database has 10 voting options ($q = 10$) with possible voting values $V = \{0.5,1,1.5,2,2.5,3,3.5,4,4.5,5\}$. <br />In the analysis, $y$ users (determined from $tag$ values) were selected globally for entire time range available in the data (9/17/1997 - 1/5/2009 ). The $x$ users were determined for each time step which was chosen as 1 day. For each time step I calculated the energy $e$ and the order parameter $m$. Details of calculations are available in R language listed in [2]. The calculations were performed for different numbers of voting options $q$ and available values $V$. Selected values of $q$ and $V$ are following <br /><br /><ol><li> $q = 3$, $V = \{2, 3, 4 \}$ </li><li> $q = 4$, $V = \{2, 3, 4, 5 \}$ </li><li> $q = 5$, $V = \{1, 2, 3, 4, 5 \}$ </li><li> $q = 6$, $V = \{1, 1.5, 2, 3, 3.5, 4\}$ </li><li> $q = 7$, $V = \{1, 1.5, 2, 2.5, 3, 3.5, 4\}$ </li><li> $q = 10$, $V = \{0.5, 1, 1.5, 2, 2.5, 3, 3.5, 4, 4.5, 5\}$ </li></ol>For each subset defined by $q$ I made an averaging fit of calculated time evolution of variables $e$ and $m$ using local polynomial regression fitting smoothing (loess) with parameters [3]: <br /> <pre class="brush: csharp"><br />loess(y ~ x, family="gaussian", span=.75, degree=1)<br /></pre> <br />All results are presented on plots below (the R source code for plots is listed in [3]). The energy $e$ (normalized to the same initial value) shows a behaviour typical for the Potts model: <a href="https://3.bp.blogspot.com/-whV6LdNOwbA/VuSvP5esneI/AAAAAAAAACE/E3vBUc-vh7oRs4a39lBHTHapvlYo2Gekw/s1600/EnergyPar.jpeg" imageanchor="1"><img border="0" src="https://3.bp.blogspot.com/-whV6LdNOwbA/VuSvP5esneI/AAAAAAAAACE/E3vBUc-vh7oRs4a39lBHTHapvlYo2Gekw/s320/EnergyPar.jpeg" /></a><br />But the most unexpected time evolution is seen on plot of the order parameter $m$: <a href="https://1.bp.blogspot.com/-d83P62VnLCo/VuSvfp85DFI/AAAAAAAAACI/D7I-Nm8o1rUXkBtaP8zB4uV91K3VhLCPw/s1600/OrderPar.jpeg" imageanchor="1"><img border="0" src="https://1.bp.blogspot.com/-d83P62VnLCo/VuSvfp85DFI/AAAAAAAAACI/D7I-Nm8o1rUXkBtaP8zB4uV91K3VhLCPw/s320/OrderPar.jpeg" /></a><br />The relaxation of the order parameter $m$ shows a two-staged process, well distinguished for $q < 6$ . The same behaviour is also visible for $q >=6$ however the steady-state value is not reached by the system yet. The final value of the order parameter also depends on the number of voting options. The stable value of $m$ parameter is higher for models with $q < 6$ ($\approx 0.6$) than for $q >=6$ ($\approx 0.4$). But this result should be checked more carefully on other datasets and it is too early to conclude this observation.<br /><br /><h4>Conclusions</h4><br />After some analysis work with the dataset from the RS, let me gather 2 main points: <br /><ol><li> two-staged relaxation process of the order parameter $m$ could be related to the different dynamical mechanisms. One of them leads to the exponential decay and the second one to the self-organizing phenomena. In terms of users behaviour, it suggests existence of two classes of users: randomly using the RS which could be responsible for the fast decay of the parameter $m$ and visitors of the RS with more stable opinions about voting subject. The stabilizing effects due to the non-random visitors will be specific rather for longer working rating webpages. Due to this feature I expect different performance of the same RS on a newly created rating website and on the rating site working for longer time . </li><li> The time scale of the order parameter $m$ decay after which the stable stage is reached is faster for smaller $q$ parameter. For the dataset used for the analysis the decays can be grouped for models with $q < 6$ and $q >=6$. This observation implies that a better performance of RS can be achieved for a system with smaller number of voting options. </li></ol><br />Any comments and opinions greatly appreciated, thanks. <br /><br /><br />Bogdan Lobodzinski <br /><br /><a href="http://dataanalytics4all.site/">Data Analytics For All consulting Service</a><br /><br /><br /><h4>References</h4><br />[1] As a data for the model I used the movie dataset created by: <br /><ul><li> [url=http://www.grouplens.org]Movielens from GroupLens research group[/url], </li><li> [url=http://www.imdb.com]IMDb website[/url], </li><li> [url=http://www.rottentomatoes.com] Rotten Tomatoes website[/url], </li></ul>build by Ivan Cantador with the collaboration of Alejandro Bellogin and Ignacio Fernandez-Tobias, members of the Information Retrieval group at <a href="http://ir.ii.uam.es/">Universidad Autonoma de Madrid</a>. The data can be downloaded from <a href="http://ir.ii.uam.es/hetrec2011//datasets.html">http://ir.ii.uam.es/hetrec2011//datasets.html site</a>. [2] the source code in R for calculation of energy $e$ and order parameter $m$ for 4 voting options ($q = 4$) with available values $V = \{2,3,4,5\}$.<br /><pre class="brush: csharp">// Code<br />library(readr)<br />library(rgl)<br />library(MASS)<br />library(reshape2)<br /><br /># Set a random seed for reproducibility<br />set.seed(1)<br /><br /># set the q value of the model<br />q0 <- 4<br /># set the value options:<br />options <- c(2,3,4,5)<br /># set the file name with output:<br />Output <- "Params_q4.csv" <br /><br />cat("reading the data\n")<br />prefix <- "../moviedata/"<br />user_rated_input <- paste0(prefix,"user_ratedmovies.dat")<br />userrate<- read.table(user_rated_input, header=TRUE)<br /><br />user_tagged_input <- paste0(prefix,"user_taggedmovies.dat")<br />usertag <- read.table(user_tagged_input, header=TRUE)<br /><br />cat("Data manipulation\n") <br /><br /># 1. replace time by secs<br />userrate$timeinDays <- as.numeric(as.POSIXlt(userrate$time, format="%m/%d/%Y"))<br />usertag$timeinDays <- as.numeric(as.POSIXlt(usertag$time, format="%m/%d/%Y"))<br /><br /># 2. rearrange data first in descending time order:<br />sort.userrate <- userrate[order(userrate$timeinHours) , ]<br />sort.usertag <- usertag[order(usertag$timeinDays) , ]<br /><br />GetMatrix <- function(inputX,inputY, inputZ) {<br /> x <- NULL<br /> y <- NULL<br /> z <- NULL<br /> x <- inputX<br /> y <- inputY<br /> z <- inputZ<br /> <br /> # check duplications:<br /> d1<-NULL<br /> d1<-data.frame(x,y)<br /> indexes<-NULL<br /> indexes<-which(duplicated(d1))<br /> if (length(indexes)) {<br /> d1<-d1[!duplicated(d1),]<br /> z<-z[-indexes]<br /> }<br /> mydf <- NULL<br /> mydf <- data.frame(d1,z)<br /> mat <- NULL<br /> mat<-as.matrix(acast(mydf, x~y, value.var="z"))<br /> mat[is.na(mat)] <- 0<br /> mat<br />}<br /><br />lowerLimit <- q0<br /><br />EnergyAv <- NULL<br />MagAv <- NULL<br />items <- NULL <br /><br />for (item in unique(sort.userrate$time)) { # <- Day's timescale <br /> tx <- NULL<br /> tx <- subset(data.frame(sort.userrate),time == item)<br /><br /> if ( min(dim(tx)) > 0 ) {<br /> merged <- NULL <br /> merged<-merge(tx,sort.usertag,by=c("movieID")) <br /> if (min(dim(merged)) > 0 ) {<br /> myMat <- NULL<br /> myMat <- GetMatrix(merged$userID.x,merged$userIDy,merged$rating)<br /> myMat1<-NULL<br /> myMat1<-myMat[!(myMat == 0)]<br /><br /> # selection of states:2,3,4,5 for q = 4 valued model:<br /> myMat1 <- myMat1[myMat1 %in% options]<br /> nrOfSpins <- length(myMat1)<br /> if ( (nrOfSpins > lowerLimit) ) {<br /> # Energy: <br /> Energy <- 0<br /> # counting nr of pairs:<br /> for (elem in table(myMat1)) {<br /> Energy <- Energy -(choose(elem, 2))<br /> }<br /> EnergyAv <- c(EnergyAv,Energy/nrOfSpins)<br /> <br /> # Order parameter Mag: <br /> Mag <- 0<br /> Mag <- (q0*max(table(myMat1))-nrOfSpins)/(q0-1)<br /> MagAv <- c(MagAv, Mag/nrOfSpins)<br /> <br /> # time:<br /> items <- c(items, item)<br /> }<br /> } <br /> }<br />}<br /><br />cat("Saving results ...\n")<br />dfq<-NULL<br />dfq<-data.frame(Time=items,Mag=MagAv,En=EnergyAv)<br />write_csv(dfq, Output )<br /><br /></pre> [3] R source code used for creation of the plots: <pre class="brush: csharp">// Code<br />library(readr)<br />require(ggplot2)<br />library(rgl)<br />library(MASS)<br />library(lattice)<br /><br /># read data<br />prefix <- "./"<br />q3_input <- paste0(prefix,"Params_q3.csv")<br />q4_input <- paste0(prefix,"Params_q4.csv")<br />q5_input <- paste0(prefix,"Params_q5.csv")<br />q6_input <- paste0(prefix,"Params_q6.csv")<br />q7_input <- paste0(prefix,"Params_q7.csv")<br />q10_input <- paste0(prefix,"Params_q10.csv")<br /><br />q3 <- read.table(q3_input, sep=",", header=TRUE)<br />q4 <- read.table(q4_input, sep=",", header=TRUE)<br />q5 <- read.table(q5_input, sep=",", header=TRUE)<br />q6 <- read.table(q6_input, sep=",", header=TRUE)<br />q7 <- read.table(q7_input, sep=",", header=TRUE)<br />q10 <- read.table(q10_input, sep=",", header=TRUE)<br /><br /># fits & plots:<br />elems <- list(q3,q4,q5,q6,q7,q10)<br /><br /># fit of the order parameter:<br />myx1 <- NULL<br />mypred1 <- NULL<br /><br />for (ind in 1:length(elems)) {<br /> tmp <- NULL<br /> tmp <- data.frame(elems[ind])<br /><br /> x <- as.numeric(as.POSIXlt(tmp$Time, format="%m/%d/%Y"))<br /> myx1 <- c(myx1,list(x))<br /> <br /> y <- with(tmp, Mag)<br /> eval.length <- dim(tmp)[1]<br /> fit.loess2= loess(y ~ x, family="gaussian", span=.75, degree=1)<br /> <br /> pred <- predict(fit.loess2, data.frame(x=x))<br /> fac<-1/pred[1]<br /> pred <- pred*fac<br /> mypred1<- c(mypred1,list(pred))<br />}<br /><br /># energy:<br /># fit of the energy parameter:<br />myx2 <- NULL<br />mypred2 <- NULL<br /><br />for (ind in 1:length(elems)) {<br /> tmp <- NULL<br /> tmp <- data.frame(elems[ind])<br /> <br /> x <- as.numeric(as.POSIXlt(tmp$Time, format="%m/%d/%Y"))<br /> myx2 <- c(myx,list(x))<br /> <br /> y <- with(tmp, En)<br /> eval.length <- dim(tmp)[1]<br /> fit.loess2= loess(y ~ x, family="gaussian", span=.75, degree=1)<br /> <br /> pred <- predict(fit.loess2, data.frame(x=x))<br /> fac<-abs(1/pred[1])<br /> pred <- pred*fac<br /> mypred2<- c(mypred2,list(pred))<br />}<br /><br /># plots:<br />xpos <- c(8.94,8.99,9.04,9.09) # x axis: log10(time) position<br />x01 <- log10(myx1[[1]])<br />origin_date <- "1970-01-01"<br />t1 <- substr(as.POSIXct(10^(x01[which.min(abs(x01-xpos[1]))]), origin = origin_date),1,10)<br />t2 <- substr(as.POSIXct(10^(x01[which.min(abs(x01-xpos[2]))]), origin = origin_date),1,10)<br />t3 <- substr(as.POSIXct(10^(x01[which.min(abs(x01-xpos[3]))]), origin = origin_date),1,10)<br />t4 <- substr(as.POSIXct(10^(x01[which.min(abs(x01-xpos[4]))]), origin = origin_date),1,10)<br />TimeLabels <- c(t1,t2,t3,t4)<br /><br />colors <- terrain.colors(6)<br /><br />plot(log10(myx1[[ind]]), mypred1[[ind]],type="l",lwd=6, col = colors[ind], xlab = "Log10(Time)", <br /> ylab = "Normalized Order parameter", <br /> ylim=c(0.2,1.0), xaxt = "n" )<br />for (i in seq(ind-1,1,-1)) {<br /> lines(log10(myx1[[i]]), mypred1[[i]],lwd=6, col = colors[i], xlab = "Time (s)", <br /> ylab = "Counts")<br />}<br />legend("topright", inset=.05, title="q-values:",c("3","4","5","6","7","10"), fill=colors[1:6], <br />horiz=TRUE)<br />axis(side = 1, at = xpos, labels = TimeLabels)#, tck=-.05)<br /><br /># energy:<br />plot(log10(myx2[[1]]), mypred2[[1]],type="l",lwd=6, col = colors[1], xlab = "Log10(Time)", <br /> ylab = "Normalized Energy", xaxt = "n")#, ylim=c(-,1.0) )<br />for (i in seq(2,ind,1)) {<br /> lines(log10(myx2[[i]]), mypred2[[i]],lwd=6, col = colors[i], xlab = "Time (s)", <br /> ylab = "Counts")<br />}<br />legend("bottomleft", inset=.05, title="q-values:",c("3","4","5","6","7","10"), fill=colors[1:6], <br />horiz=TRUE)<br />axis(side = 1, at = xpos, labels = TimeLabels)#, tck=-.05)<br /><br /></pre>Bogdan Lobodzinskihttp://www.blogger.com/profile/09289422592105592639noreply@blogger.com0tag:blogger.com,1999:blog-4412689276279452501.post-24010242575088621282016-03-13T19:39:00.001+01:002021-05-14T21:51:54.977+02:00How Data Analytics can help small companies ?Trying to operate on the market of micro, small and medium-sized enterprises as a data analyst serving solutions based on the machine learning techniques, I have to say - it is a difficult business. <br /><br />In my opinion, the difficulties arise due to two main, entangled reasons: <br /><ol><li> completely missing knowledge about a potential of data analytics. Most company owners don't even accept a though that someone from outside of the firm can suggest how to improve his business productivity, </li><li> if someone sees the need of a data analytics, the second problem appears: it is the cost of such a project. It can be a serious problem if it is seen as a single payment without noticing a new business landscape which gets opened by the results of the data analysis. </li></ol>Let us start with the second point: data analytics project costs.<br /><br />First of all, a usual thinking is that a data analytics requires enormously complex hardware and software infrastructure, therefore it will cost much too much. The truth is just the opposite. All tools which are needed for data analytics tasks of small companies can be completed during a few working days without spending a penny. Actually, it is not fully true, you have to have a good, powerful notebook with access to the network. Already having a computer, what else do you need at the beginning ?<br /><br /><ol><li> Linux as a free operational system, and software: </li><li> Python or/and R (in this case also Rstudio). </li></ol>All of the above is available for free and downloadable from the Internet as an open source software. The most important part of the whole collection is your business database. Again, even if you collect data using commercial software specific for your activity, it is possible to convert most of the available formats into more accessible ones for the R or Python form. Sometimes, that work might require some effort but in general it is doable.<br />More problematic is the situation when the company data are on the paper only. What to do in such a case ?<br />Maybe your accountant can help somehow - in communication with the tax office some forms of digital data have to be used anyway.<br />Another solution is to initialize the data gathering from the scratch. It can be realized using open source databases installed on a cloud. The cloud is not a free choice but the management costs are really negligible if one compares the cost of cloud computing and storage with other business expenses. In case of a cloud usage, we have to add a note about security of your data, especially in terms of unauthorized external access to your data. Solution is very simple: the data analysis doesn't need real values in your database entries. <br />It is enough to replace, for example, real addresses of the company clients by short unique strings. Similar encryption can be done with numbers, using a common factor for all values in a given row. The real meaning of the unique strings and numerical factors remains in a company's hands.<br />If needed, one can use already existing datasets available for <a href="http://www.datasciencecentral.com/profiles/blogs/big-data-sets-available-for-free">free</a>.<br /><br />Now, we get to the point where a data expert becomes a crucial person. The data scientist can merge the entrepreneur business knowledge with mathematics and practical machine learning solutions. This can lead to a better understanding of your business experience. But the final move belongs to the company managers, data analytics would lead to nothing if the results were not introduced into practical realizations. <br /><br />Work of the data expert(s), usually includes <br /><ol><li> consultations: when points like these are discussed: <ul><li> what the company would like to develop, explain, understand or predict, </li><li> availability of business data and how they are compatible with the company's goal, </li><li> preparation of a concluding question e.g. the final goal of the data analysis, </li></ul></li><li> pilot solution: a creation of a test model which can be validated on the existing data and tested on a new set of data, </li><li> final realization: preparation of software tools which can be used on demand in daily business operations or on a regular basis using old and newly created data. </li></ol>Between the lines written above a number of interactive actions is included where all obstacles or unpredicted behaviours are discussed. All that is performed until the desired result is achieved. The usual working time of the expert can be estimated between 50 hours (a week) for a micro projects up to several hundreds hours of work. <br /><br />Now, one can ask how much data analytics products per working hour might cost ? The hourly rate can be estimated as 30 - 100 Euros. So, the final cost can vary between 1500 - 50000 Euro and more. <br /><br />How to measure the efficiency of a data analytics project ?<br />A research performed by D. Barton and D. Court which was based on 165 large publicly traded firms shows that Data-driven decision-making can increase the output and productivity by 3-5% beyond the traditional improvement steps (Dominic Barton and David Court, <i>Making advanced analytics work for you</i>, Harvard Business Review, October 2012, Volume 90, Number 10, pp. 78–83). Using this estimation and assuming the smallest increase of 3% of a company output, a minimum enterprise outcome would be about 50 000 Euro for full recompensation of a smallest Data analytics project cost. <br /><br />We treat the subject very generally, therefore some company owners will not be convinced why they should start to use data-driven decisions instead of relaying on the well grounded on the experience intuition . The numbers: 3-5% of outcome increase (set by the classical actions estimated by authors in cited above research paper) seem to be too small to be used as a solid argument in a discussion with small-firm owners.<br /><br />Yet, let me add a few arguments which, I hope, can change a bit the dominated view of data analytics in small business. <br /><ol><li> The most important step: collection of data, especially in small companies is difficult due to the lack of knowledge and free manpower. However, that issue can be easily automated and (what is not negligible) the tool can be fully owned by the company. Collecting sufficient amounts of data takes time, it could be a quite long process in case of small-firm segments. Therefore, the sooner the data collection process will start, the sooner analytical process will become beneficial. </li><li> The data-driven management system requires more formalized and structured approach. It could be a difficult point in the transformation to the data-driven manner. But by answering simple questions (sometimes completely neglected and treated as a not important at all) one can achieve the biggest goals. Just a few examples of questions: <br />Who is buying a given flavour of a bread ?<br /> How is the buying of bread correlated with time ?<br /> Which cookies prefer young, mature and older customers ? etc. <br />All these answers can be provided by data analytics. And it is straightforward to notice that knowing the answers and following them in real world means clearly higher revenue. <br /> </li><li> What if the results of data analytics are consistent with the firm-owner intuition ? In our opinion it is a wrong question: even if data-driven development suggestions are compatible with the well established experience of the company leader, we are talking about specific numbers: how many cookies should be delivered to the shop, how many breads should be produced, etc. Do you believe that any, even the best intuition would provide the same numbers ?. Obviously not. Therefore, the initial question should be replaced by the statement: The data-driven results are capable to increase assurance of the manager's intuition. <br /> </li><li> and finally the non BigData conclusion: new technologies in a company business opens the firm to new ideas and tedious work becomes more interesting. </li></ol>So, what do you think Dear Reader ? Are you ready for innovations in your view of the company's management style ? <br /><br />Bogdan Lobodzinski <br /><a href="http://dataanalytics4all.site/">Data Analytics For All Consulting Service</a>Bogdan Lobodzinskihttp://www.blogger.com/profile/09289422592105592639noreply@blogger.com0